home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cnstrnts / thinglab.lha / ThingLabII / ThingLabII.v2.st < prev    next >
Text File  |  1993-07-24  |  471KB  |  15,013 lines

  1. "ThingLabII System of (20 May 1990 3:31:38 pm )"!
  2.  
  3. "Copyright (c) 1989 and 1990, Regents of the University of Washington.
  4. Permission is granted to use or reproduce this program for research
  5. and development purposes only. For information regarding the use of this
  6. program in a commercial product, contact:
  7.  
  8.     Office of Technology Transfer
  9.     University of Washington
  10.     4225 Roosevelt Way NE, Suite 301
  11.     Seattle, WA  98105
  12.  
  13. ThingLab II was written between 1988 and 1990 by John Maloney and
  14. Bjorn N. Freeman-Benson with the guidance of Alan Borning."!
  15.  
  16.  
  17. !Number methodsFor: 'ThingLabII'!
  18.  
  19. asNonZero
  20.     "To avoid divide-by-zero errors, answer a very small number if I am zero."
  21.  
  22.     ^(self = 0)
  23.         ifTrue: [0.0000000001]
  24.         ifFalse: [self]! !
  25.  
  26. !Symbol methodsFor: 'ThingLabII'!
  27.  
  28. path
  29.     "Answer an array of the part names that comprise the compound path selector. For example, '#fat.cat.hat path' returns an array of three symbols, #fat, #cat, and #hat."
  30.  
  31.     | result currentPart |
  32.     result _ OrderedCollection new.
  33.     currentPart _ WriteStream on: (String new: 16).
  34.     self do:
  35.         [: ch |
  36.          (ch = $.)
  37.             ifTrue:
  38.                 [result addLast: currentPart contents asSymbol.
  39.                  currentPart reset]
  40.             ifFalse: [currentPart nextPut: ch]].
  41.     result addLast: currentPart contents asSymbol.
  42.     ^result asArray! !
  43.  
  44. !BitBlt methodsFor: 'ThingLabII'!
  45.  
  46. drawFrom: p1 to: p2
  47.     "This line drawing method was improved by John Maloney to do more intelligent clipping. If the line (p1,p2) is entirely INSIDE the clipping box, this method gives results that are identical to the original line drawing method. If the line is entirely OUTSIDE the clipping box, it detects this early and avoids the cost of drawing it. Finally, if the line is PARTIALLY inside the clipping box, the portion entirely inside the clipping box computed and can be drawn by the primitive. If the pen form is large, you may notice a slight difference from the results given by the normal drawFrom:to: method on the right/bottom of the clipping box."
  48.  
  49.     | offset startPoint endPoint clipOrigin clipCorner clippedLine |
  50.     width _ sourceForm width.
  51.     height _ sourceForm height.
  52.     offset _ sourceForm offset.
  53.  
  54.     "always draw down, or at least left-to-right"
  55.     ((p1 y = p2 y and: [p1 x < p2 x])
  56.         or: [p1 y < p2 y])
  57.             ifTrue: [startPoint _ p1 + offset. endPoint _ p2 + offset]
  58.             ifFalse: [startPoint _ p2 + offset. endPoint _ p1 + offset].
  59.  
  60.     "The clipping rectangle specified by the sender is intersected with the destination form. Then the corner of the result is inset by the extent of the pen form. This clipping rectangle is used to compute 'clippedLine'. clipped line is a triple <visibleFlag, startPoint, endPoint>. If visibleFlag is false, no part of the line is visible in the clipping box. If visibleFlag is true, clippedLine can be drawn with the primitive, which is fast."
  61.     clipOrigin _ (clipX@clipY) max: (0@0).
  62.     clipCorner _ (clipWidth@clipHeight) min: (destForm extent).
  63.     clippedLine _
  64.         (ClippingRectangle
  65.             origin: clipOrigin
  66.             corner: clipCorner - (width@height))
  67.                 clipFrom: startPoint to: endPoint.
  68.  
  69.     (clippedLine first)
  70.         ifTrue:
  71.             ["draw the visible part of the line"
  72.              self privateDrawFrom: (clippedLine at: 2) to: (clippedLine at: 3)]
  73.         ifFalse:
  74.             ["the line is entirely outside the clipping region"].!
  75.  
  76. privateDrawFrom: p1 to: p2
  77.     "Added by John Maloney for faster line drawing."
  78.  
  79.     destX _ p1 x rounded.
  80.     destY _ p1 y rounded.
  81.     self drawLoopX: ((p2 x - p1 x) rounded) Y: ((p2 y - p1 y) rounded)! !
  82.  
  83. !Object methodsFor: 'ThingLabII'!
  84.  
  85. destroy
  86.     "'Destroy' is ThingLabII-ese for 'release'."
  87.  
  88.     self release.!
  89.  
  90. filterOwners: aCollection
  91.     "Filter the 'allOwners' method and the collection used to collect all owners out of the given collection."
  92.  
  93.     | filtered allOwnersMethod |
  94.     filtered _ aCollection copy.
  95.     allOwnersMethod _ aCollection
  96.         detect:
  97.             [: e |
  98.              (e isMemberOf: MethodContext) and:
  99.              [((e receiver class) 
  100.                 selectorAtMethod: e method
  101.                 setClass: [: mc | "ignore"]) == #allOwners]]
  102.         ifNone: [^self].
  103.     filtered remove: allOwnersMethod.
  104.     filtered _ filtered select:
  105.         [: e |
  106.          ((e isMemberOf: OrderedCollection) and:
  107.           [e includes: allOwnersMethod]) not].
  108.     ^filtered!
  109.  
  110. includesRoot: aCollection
  111.     "Answer true if the given collection includes the system dictionary 'Smalltalk'."
  112.  
  113.     aCollection do:
  114.         [: element |
  115.          (element == Smalltalk) ifTrue: [^true].
  116.          (element class isMemberOf: Metaclass) ifTrue: [^true].
  117.          (Smalltalk includesKey: element) ifTrue: [^true]].
  118.     ^false!
  119.  
  120. isThing
  121.     "Answer true if I am a Thing. Normal Smalltalk Objects are not Things."
  122.  
  123.     ^false!
  124.  
  125. traceOwners
  126.     "Build the transitive closure of the 'owners' relation. That is, starting with me, add my owners, then my owners' owners, then their owners, and so on until no new objects are added or until we encounter the 'Smalltalk' object, the globals dictionary."
  127.  
  128.     | allOwners allRoots toDo obj owners |
  129.     allOwners _ IdentitySet new: 100.
  130.     allRoots _ OrderedCollection new.
  131.     toDo _ OrderedCollection new.
  132.     toDo add: self.
  133.     [toDo isEmpty] whileFalse:
  134.         [obj _ toDo removeFirst.
  135.          owners _ nil.
  136.          Smalltalk primGarbageCollect.
  137.          owners _ obj allOwners.
  138.          owners remove: thisContext ifAbsent: [].
  139.          owners remove: allOwners ifAbsent: [].
  140.          owners remove: allRoots ifAbsent: [].
  141.          owners remove: toDo ifAbsent: [].
  142.          owners remove: obj ifAbsent: [].
  143.          owners remove: owners ifAbsent: [].
  144.          owners _ self filterOwners: owners.
  145.          (self includesRoot: owners)
  146.             ifTrue: [allRoots add: obj]
  147.             ifFalse:
  148.                 [owners do:
  149.                     [: owner |
  150.                      ((allOwners includes: owner) or:
  151.                       [allRoots includes: owner]) ifFalse:
  152.                         [allOwners add: owner.
  153.                          toDo add: owner]]].
  154.          Transcript show: allOwners size printString; cr].
  155.     ^Array    
  156.         with: allOwners asOrderedCollection
  157.         with: allRoots!
  158.  
  159. warning: ignored
  160.     "Browsing the senders of this message can be used to find 'soft' spots in the ThingLabII implementation."! !
  161.  
  162. !ClassDescription methodsFor: 'ThingLabII'!
  163.  
  164. organization: anOrganizer
  165.  
  166.     organization _ anOrganizer! !
  167.  
  168. !ScreenController methodsFor: 'ThingLabII'!
  169.  
  170. announceThingLabII: aForm
  171.     "If the given form is not nil, then pop up the ThingLabII intro picture and wait until the user clicks the mouse."
  172.  
  173.     (aForm notNil)
  174.         ifTrue: [IntroPicture openOn: aForm].!
  175.  
  176. openControlPanel
  177.     "Pop up the ThingLabII Control Panel."
  178.  
  179.     ThingLabIIControlPanel open.!
  180.  
  181. openTopBin
  182.     "Open a ThingLabII PartsBin view."
  183.  
  184.     PartsBinView openOn: (PartsBin topBin).!
  185.  
  186. quit
  187.     "Save this image and quit from Smalltalk, quit without saving the image, or return to normal operations, depending on the respose of the user to a menu query."
  188.  
  189.     | menu index |
  190.     menu _ PopUpMenu
  191.         labels:
  192. ' Save, then quit 
  193.  Quit, without saving 
  194.  Continue '
  195.         lines: #(1 2).
  196.     index _ menu startUp.
  197.     (index = 1)
  198.         ifTrue: [self save: true].        "save, then quit"
  199.     (index = 2)
  200.         ifTrue: [Smalltalk quit].        "quit without saving"
  201.  
  202.     "otherwise, resume normal Smalltalk operations"!
  203.  
  204. save
  205.     "Do a system snapshot but don't quit."
  206.  
  207.     self save: false.    "continue after saving"!
  208.  
  209. save: quitAfterSaving
  210.     "Do a system snapshot and quit if 'quitAfterSaving' is true. We pop up the ThingLabII Intro window after saving so it will be the first thing the user see when re-starting the saved image. This means that it also pops up after the save operation. Popping up the ThingLabII Intro window can be disabled by holding down the shift key while performing this operation."
  211.  
  212.     | prefix form |
  213.     prefix _ Smalltalk getImagePrefix.
  214.     prefix isEmpty ifTrue: [^self].
  215.     form _ nil.
  216.     sensor leftShiftDown ifFalse:
  217.         [(FileDirectory includesKey: 'ThingLabII.form')
  218.             ifTrue: [form _ Form readFrom: 'ThingLabII.form']].
  219.     Smalltalk saveAs: prefix thenQuit: quitAfterSaving.
  220.     self announceThingLabII: form.    "This is a noop if form is nil."! !
  221.  
  222. !ScreenController class methodsFor: 'ThingLabII class initialization'!
  223.  
  224. initialize
  225.     "Initialize the System Menu."
  226.  
  227.     "ScreenController initialize.
  228.     ScreenController allInstancesDo: [:c | c initializeYellowButtonMenu]"
  229.  
  230.     ScreenYellowButtonMenu _
  231.         PopUpMenu
  232.             labels: 
  233. 'restore display
  234. garbage collect
  235. exit project
  236. browser
  237. workspace
  238. file list
  239. file editor
  240. terminal
  241. project
  242. ThingLabII Parts Bin
  243. ThingLabII Control Panel
  244. system transcript
  245. system workspace
  246. desk top
  247. save
  248. quit'
  249.             lines: #(3 9 11 12 13).
  250.     ScreenYellowButtonMessages _
  251.             #(restoreDisplay garbageCollect exitProject
  252.             openBrowser openWorkspace openFileList openFileEditor 
  253.             openCshView  openProject 
  254.             openTopBin openControlPanel
  255.             openTranscript openSystemWorkspace 
  256.             openDeskTop save quit).! !
  257.  
  258. !AssignmentNode methodsFor: 'ThingLabII'!
  259.  
  260. apply: aBlock
  261.  
  262.     (aBlock value: self)
  263.         ifTrue:
  264.             [variable apply: aBlock.
  265.              value apply: aBlock].!
  266.  
  267. specificMatch: aTree using: matchDict
  268.     "See ParseNode>specificMatch:using:"
  269.  
  270.     ^(variable match: aTree variable using: matchDict) and:
  271.       [value match: aTree value using: matchDict]!
  272.  
  273. transformBy: aBlock
  274.  
  275.     | result |
  276.     result _ self copy.
  277.     result
  278.         variable: (variable transformBy: aBlock)
  279.         value: (value transformBy: aBlock).
  280.     ^aBlock value: result!
  281.  
  282. value
  283.  
  284.     ^value!
  285.  
  286. variable
  287.  
  288.     ^variable! !
  289.  
  290. !BlockNode methodsFor: 'ThingLabII'!
  291.  
  292. apply: aBlock
  293.  
  294.     (aBlock value: self) ifTrue:
  295.         [statements do:
  296.             [: statement | statement apply: aBlock]].!
  297.  
  298. arguments: args
  299.  
  300.     arguments _ args.!
  301.  
  302. specificMatch: aTree using: matchDict
  303.     "See ParseNode>specificMatch:using:"
  304.  
  305.     (statements size = aTree statements size) ifFalse: [^false].
  306.     statements with: aTree statements do:
  307.         [: s1 : s2 |
  308.          (s1 match: s2 using: matchDict) ifFalse: [^false]].
  309.  
  310.     ^true    "all statements match"!
  311.  
  312. statements
  313.  
  314.     ^statements!
  315.  
  316. statements: statementList
  317.  
  318.     statements _ statementList.!
  319.  
  320. transformBy: aBlock
  321.  
  322.     | result |
  323.     result _ self copy.
  324.     result arguments:
  325.         (arguments collect:
  326.             [: arg | arg transformBy: aBlock]).
  327.     result statements:
  328.         (statements collect:
  329.             [: statement | statement transformBy: aBlock]).
  330.     ^aBlock value: result! !
  331.  
  332. !CascadeNode methodsFor: 'ThingLabII'!
  333.  
  334. apply: aBlock
  335.  
  336.     (aBlock value: self)
  337.         ifTrue:
  338.             [receiver apply: aBlock.
  339.              messages do:
  340.                 [: msg | msg apply: aBlock]].!
  341.  
  342. specificMatch: aTree using: matchDict
  343.     "See ParseNode>specificMatch:using:"
  344.  
  345.     (receiver match: aTree receiver using: matchDict) ifFalse: [^false].
  346.     (messages size =  aTree messages size) ifFalse: [^false].
  347.     messages with: aTree messages do:
  348.         [: m1 : m2 |
  349.          (m1 match: m2 using: matchDict) ifFalse: [^false]].
  350.  
  351.     ^true    "receiver and messages all match"!
  352.  
  353. transformBy: aBlock
  354.  
  355.     | result |
  356.     result _ self copy.
  357.     result
  358.         receiver: (receiver transformBy: aBlock)
  359.         messages:
  360.             (messages collect:
  361.                 [: msg | msg transformBy: aBlock]).
  362.     ^aBlock value: result! !
  363.  
  364. !LeafNode methodsFor: 'ThingLabII'!
  365.  
  366. apply: aBlock
  367.  
  368.     aBlock value: self.!
  369.  
  370. transformBy: aBlock
  371.  
  372.     ^aBlock value: self copy! !
  373.  
  374. !LiteralNode methodsFor: 'ThingLabII'!
  375.  
  376. specificMatch: aTree using: matchDict
  377.     "See ParseNode>specificMatch:using:"
  378.  
  379.     ^key = aTree key! !
  380.  
  381. !MessageNode methodsFor: 'ThingLabII'!
  382.  
  383. apply: aBlock
  384.  
  385.     (aBlock value: self)
  386.         ifTrue:
  387.             [receiver notNil
  388.                 ifTrue: [receiver apply: aBlock].
  389.              arguments do: [: arg | arg apply: aBlock]].!
  390.  
  391. arguments
  392.  
  393.     ^arguments!
  394.  
  395. arguments: argList
  396.  
  397.     arguments _ argList.!
  398.  
  399. moveVariableToFarLeft: aVariable
  400.     "Move the variable with this key as far left as possible using the message 'swapSides'."
  401.  
  402.     | newMe count oldMe argWithVar i newArg |
  403.     newMe _ self copy.
  404.     count _ arguments size + 2.
  405.     [(count > 0) and:
  406.        [((newMe receiver allVariables includes: aVariable) not) and: 
  407.         [oldMe _ newMe.
  408.          newMe _ newMe swapSides.
  409.          newMe ~= oldMe]]]
  410.             whileTrue: [count _ count - 1].
  411.     (count = 0) ifTrue:
  412.         [self error: 'Never found the variable while swapping'].
  413.     (newMe receiver allVariables includes: aVariable)
  414.         ifTrue:
  415.             [newMe receiver:
  416.                 (newMe receiver moveVariableToFarLeft: aVariable)]
  417.         ifFalse: 
  418.             [argWithVar _ newMe arguments
  419.                 detect: [: arg | arg allVariables includes: aVariable]
  420.                 ifNone: [self error:
  421.                         'Can''t find the variable in the swapped equation'].
  422.              i _ newMe arguments indexOf: argWithVar.
  423.              newArg _
  424.                 (newMe arguments at: i) moveVariableToFarLeft: aVariable.
  425.              newMe arguments at: i put: newArg].
  426.     ^newMe!
  427.  
  428. receiver
  429.  
  430.     ^receiver!
  431.  
  432. receiver: newReceiver
  433.  
  434.     receiver _ newReceiver.!
  435.  
  436. selector
  437.  
  438.     ^selector!
  439.  
  440. specificMatch: aTree using: matchDict
  441.     "See ParseNode>specificMatch:using:"
  442.  
  443.     (receiver match: aTree receiver using: matchDict) ifFalse: [^false].
  444.     (selector match: aTree selector using: matchDict) ifFalse: [^false].
  445.     (arguments size = aTree arguments size) ifFalse: [^false].
  446.     arguments with: aTree arguments do:
  447.         [: arg1 : arg2 |
  448.          (arg1 match: arg2 using: matchDict) ifFalse: [^false]].
  449.  
  450.     ^true    "receiver, selector, and arguments all match"!
  451.  
  452. transformBy: aBlock
  453.  
  454.     | result |
  455.     result _ self copy.
  456.     (receiver notNil) ifTrue:
  457.         [result receiver: (receiver transformBy: aBlock)].
  458.     result arguments:
  459.         (arguments collect:
  460.             [: arg | arg transformBy: aBlock]).
  461.     ^aBlock value: result! !
  462.  
  463. !MethodNode methodsFor: 'ThingLabII'!
  464.  
  465. apply: aBlock
  466.  
  467.     (aBlock value: self)
  468.         ifTrue:
  469.             [block apply: aBlock].!
  470.  
  471. arguments: argList
  472.  
  473.     arguments _ argList.!
  474.  
  475. block
  476.  
  477.     ^block!
  478.  
  479. block: theBlock
  480.  
  481.     block _ theBlock.!
  482.  
  483. specificMatch: aTree using: matchDict
  484.     "See ParseNode>specificMatch:using:"
  485.  
  486.     (self selector = aTree selector) ifFalse: [^false].
  487.     (block match: aTree block using: matchDict) ifFalse: [^false].
  488.     (arguments size = aTree arguments size) ifFalse: [^false].
  489.     arguments with: aTree arguments do:
  490.         [: arg1 : arg2 |
  491.          (arg1 match: arg2 using: matchDict) ifFalse: [^false]].
  492.  
  493.     ^true    "selector, block, and arguments all match"!
  494.  
  495. transformBy: aBlock
  496.  
  497.     | result |
  498.     result _ self copy.
  499.     result arguments:
  500.         (arguments collect:
  501.             [: arg | arg transformBy: aBlock]).
  502.     result block: (block transformBy: aBlock).
  503.     ^aBlock value: result! !
  504.  
  505. !ParseNode methodsFor: 'ThingLabII-Equations'!
  506.  
  507. match: targetTree using: matchDict 
  508.     "Match myself as a pattern against the target tree and answer true if a match is found. Sometimes I represent a pattern and my variables may match complete subtrees of targetTree. In such cases, the sender supplies an empty Dictionary, matchDict, that is used to map pattern variables to the corresponding subtrees of the target tree. After the match, the dictionary can be used to find which variables matched which subtrees. Sometimes it is desirable to find an exact match, with no variable substitutions. This case is indicated by supplying a 'nil' matchDict. See VariableNode>match:using for further details."
  509.  
  510.     ^(targetTree isMemberOf: self class) and:
  511.       [self specificMatch: targetTree using: matchDict]!
  512.  
  513. moveVariableToFarLeft: aVariable
  514.     "Move the variable with this key as far left as possible using the message 'swapSides'."
  515.  
  516.     self subclassResponsibility!
  517.  
  518. removeNodesSurrounding: aVariable
  519.     "Repeatedly apply restructuring rules until the given variable has been isolated. If at any point we fail to find a restructuring rule to apply, report and error and give up."
  520.  
  521.     | dictOrNil theTree newTree |
  522.     theTree _ self.
  523.     [(theTree receiver isMemberOf: VariableNode)
  524.         and: [theTree receiver key = aVariable]]
  525.         whileFalse: 
  526.             [EquationTranslator restructureRules
  527.                 detect: 
  528.                     [: rule | 
  529.                      dictOrNil _ rule matches: theTree.
  530.                      dictOrNil notNil
  531.                         and: [newTree _ rule applyUsing: dictOrNil.
  532.                             newTree receiver allVariables includes: aVariable]]
  533.                 ifNone:
  534.                     [^self error: 'Can''t reduce the left side because
  535. no rule matches the equation:
  536.     ', theTree printString].
  537.             theTree _ newTree].
  538.  
  539.     ^theTree!
  540.  
  541. restructureForAssigningTo: aVarKey
  542.  
  543.     (self isMemberOf: MessageNode) ifFalse:
  544.         [self error: 'Implementation Error: Expected a MessageNode'].
  545.  
  546.     (self allVariables includes: aVarKey) ifFalse:
  547.         [self error: 'The equation:
  548.     ', self printString, '
  549. does not contain the desired variable:
  550.     ', aVarKey].
  551.  
  552.     ^(self moveVariableToFarLeft: aVarKey)
  553.         removeNodesSurrounding: aVarKey!
  554.  
  555. specificMatch: aTree using: matchDict
  556.     "Assuming aTree is a ParseNode like me, do a field-by-field comparison between us and answer true if we match. See match:using for further details."
  557.  
  558.     self subclassResponsibility!
  559.  
  560. swapSides
  561.     "Apply the first re-order rule that matches me and return the resulting parse tree. If no rule matches me, return myself."
  562.  
  563.     | dictOrNil |
  564.     EquationTranslator reorderRules do: 
  565.         [: rule | 
  566.          dictOrNil _ rule matches: self.
  567.          (dictOrNil notNil) ifTrue:
  568.             [^rule applyUsing: dictOrNil]].
  569.     ^self! !
  570.  
  571. !ParseNode methodsFor: 'ThingLabII'!
  572.  
  573. allVariables
  574.     "Answer a set containing all variables used in this parse tree."
  575.  
  576.     | vars |
  577.     vars _ IdentitySet new.
  578.     self apply:
  579.         [: node |
  580.          (node isMemberOf: VariableNode)
  581.             ifTrue: [vars add: node name asSymbol].
  582.          true].
  583.  
  584.     self removePredefinedVarsFrom: vars.
  585.     ^vars!
  586.  
  587. assignedTo
  588.     "Answer a collection of the variables assigned to in this parse tree."
  589.  
  590.     | vars |
  591.     vars _ IdentitySet new.
  592.     self apply:
  593.         [: node |
  594.          (node isMemberOf: AssignmentNode)
  595.             ifTrue: [vars add: node variable name asSymbol].
  596.          true].
  597.  
  598.     self removePredefinedVarsFrom: vars.
  599.     ^vars!
  600.  
  601. referenced
  602.     "Answer a collection of the variables that are referenced but not assigned to in this parse tree."
  603.  
  604.     | vars |
  605.     vars _ IdentitySet new.
  606.     self apply:
  607.         [: node |
  608.          (node isMemberOf: VariableNode)
  609.             ifTrue: [vars add: node name asSymbol. true]
  610.             ifFalse:
  611.                 [(node isMemberOf: AssignmentNode)
  612.                     ifTrue: [vars addAll: node value referenced. false]
  613.                     ifFalse: [true]]].
  614.  
  615.     self removePredefinedVarsFrom: vars.
  616.     ^vars!
  617.  
  618. removePredefinedVarsFrom: varList
  619.     "Remove the pre-defined variable names from the given collection."
  620.  
  621.     #(self super true false nil thisContext) do:
  622.         [: predefinedVar |
  623.             varList remove: predefinedVar ifAbsent: []].!
  624.  
  625. transformBy: aBlock
  626.     "Answer a copy of the parse tree whose root is me, transformed by the given block. The block takes one argument, some kind of ParseNode, and returns some transformation of the node (or the node itself). For example, the null transformation (which copies the parse tree) is:
  627.     aParseTree transformBy: [: node | node]"
  628.  
  629.     self subclassResponsibility! !
  630.  
  631. !ReturnNode methodsFor: 'ThingLabII'!
  632.  
  633. apply: aBlock
  634.  
  635.     (aBlock value: self)
  636.         ifTrue:
  637.             [expr apply: aBlock].!
  638.  
  639. expr
  640.  
  641.     ^expr!
  642.  
  643. expr: expression
  644.  
  645.     expr _ expression.!
  646.  
  647. specificMatch: aTree using: matchDict
  648.     "See ParseNode>specificMatch:using:"
  649.  
  650.     ^expr match: aTree expr using: matchDict!
  651.  
  652. transformBy: aBlock
  653.  
  654.     | result |
  655.     result _ self copy.
  656.     result expr: (expr transformBy: aBlock).
  657.     ^aBlock value: result! !
  658.  
  659. !SelectorNode methodsFor: 'ThingLabII'!
  660.  
  661. specificMatch: aTree using: matchDict
  662.     "See ParseNode>specificMatch:using:"
  663.  
  664.     ^key = aTree key! !
  665.  
  666. !VariableNode methodsFor: 'ThingLabII'!
  667.  
  668. mapBy: mappingDict
  669.  
  670.     ^mappingDict at: key ifAbsent: [self]!
  671.  
  672. match: targetTree using: matchDict
  673.     "A variable in a pattern may represent an entire subtree. However, if the variable appears multiple times in the pattern then the associated subtree must be the same each time. There are two ways to use the match:using: function: 1.) allowing variables to match arbitrary subtrees or 2.) requiring an exact match (to verify that two subtrees are identical). We indicate the difference by supplying a 'nil' matchDict when we wish to make an exact match."
  674.  
  675.     | binding |
  676.     (matchDict isNil)
  677.         ifTrue:
  678.             ["we must have an exact match"
  679.              ^(targetTree isMemberOf: VariableNode) and:
  680.                [name = targetTree name & key = targetTree key]]
  681.         ifFalse:
  682.             [binding _ matchDict
  683.                         at: key
  684.                         ifAbsent:
  685.                             [matchDict at: key put: targetTree.
  686.                              ^true].
  687.              "if we already have a binding for this variable the binding must exactly match the current subtree"
  688.              ^binding match: targetTree using: nil].!
  689.  
  690. moveVariableToFarLeft: aVariable
  691.     "Move the variable with this key as far left as possible using the message 'swapSides'. This is a noop for variable nodes."
  692.  
  693.     ^self!
  694.  
  695. name
  696.  
  697.     ^name! !
  698.  
  699. Object subclass: #GraphLayout
  700.     instanceVariableNames: 'vertexCount vertices transitions lengths springConstants forces maxForce '
  701.     classVariableNames: ''
  702.     poolDictionaries: ''
  703.     category: 'ThingLabII-UI-Layout'!
  704.  
  705.  
  706. !GraphLayout methodsFor: 'initialize-release'!
  707.  
  708. placeVerticesAroundCircle
  709.     "Place vertices evenly spaced around a circle."
  710.  
  711.     | deltaTheta theta v |
  712.     deltaTheta _ (Float pi * 2.0) / vertexCount asFloat.
  713.     theta _ Float pi / 2.0.
  714.     vertices do:
  715.         [: v |
  716.          v x: 170 + (70 * theta cos).
  717.          v y: 170 + (70 * theta sin).
  718.          theta _ theta + deltaTheta].!
  719.  
  720. setupConstants
  721.     "Calculate the spring and length constants for each pair of vertices. Since these are symmetric relations, we need only compute half the matrix; the other half is filled in by symmetry. We assume that the vertices list and transition matrix have already been initialized."
  722.  
  723.     | maxDistance distances arcLength idealLength springConst |
  724.     vertexCount _ vertices size.
  725.     distances _ ShortestPaths computeDistances: transitions.
  726.     maxDistance _ 1.
  727.     distances rows do:
  728.         [: row |
  729.          row do:
  730.             [: dist | (dist > maxDistance) ifTrue: [maxDistance _ dist]]].
  731.     arcLength _ (200 // maxDistance) max: 75.
  732.     lengths _ Matrix square: vertexCount.
  733.     springConstants _ Matrix square: vertexCount.
  734.     1 to: (vertexCount - 1) do:
  735.         [: i |
  736.         (i+1) to: vertexCount do:
  737.             [: j |
  738.              dist _ distances row: i col: j.
  739.              idealLength _ (arcLength * dist) asFloat.
  740.              springConst _ 0.30 / (dist * dist) asFloat.    "unstable if const >> 0.35"
  741.              lengths row: i col: j put: idealLength.
  742.              lengths row: j col: i put: idealLength.
  743.              springConstants row: i col: j put: springConst.
  744.              springConstants row: j col: i put: springConst]].!
  745.  
  746. vertices: vertexList transitions: transitionMatrix
  747.     "Layout the connected graph with the given set of vertices and transition matrix. If the graph is not connect, its components should be laid out individually."
  748.  
  749.     vertices _ vertexList.
  750.     transitions _ transitionMatrix.
  751.     self setupConstants.
  752.     self placeVerticesAroundCircle.! !
  753.  
  754. !GraphLayout methodsFor: 'force-based method'!
  755.  
  756. computeForces
  757.     "Compute the forces vector. The force on each vertex is the vector sum of the component forces of all springs attached to the vertex."
  758.  
  759.     | i j lengthsRow springConstantsRow vectorX vectorY dist idealLength magnitude forceX forceY totalForce |
  760.  
  761.     forces _ (1 to: vertexCount) collect: [: i | 0.0@0.0].
  762.     i _ 1.
  763.     [i < vertexCount] whileTrue:
  764.         [lengthsRow _ lengths row: i.
  765.          springConstantsRow _ springConstants row: i.
  766.          j _ i + 1.
  767.          [j <= vertexCount] whileTrue:
  768.             [vectorX _ (vertices at: i) x - (vertices at: j) x.
  769.              vectorY _ (vertices at: i) y - (vertices at: j) y.
  770.              dist _ ((vectorX * vectorX) + (vectorY * vectorY)) sqrt.
  771.              (dist = 0.0)
  772.                 ifTrue:
  773.                     ["generate arbitrary force vector if vertices coincide"
  774.                      magnitude _ 10.0.
  775.                      forceX _ magnitude.
  776.                      forceY _ 0.0]
  777.                 ifFalse:
  778.                     [idealLength _ (lengthsRow at: j).
  779.                      magnitude _
  780.                         (springConstantsRow at: j) * (idealLength - dist) / dist.
  781.                      forceX _ vectorX * magnitude.
  782.                      forceY _ vectorY * magnitude].
  783.  
  784.              "Note: a positive vector = an outward force on both vertices"
  785.              totalForce _ forces at: i.
  786.              totalForce x: (totalForce x + forceX).
  787.              totalForce y: (totalForce y + forceY).
  788.              totalForce _ forces at: j.
  789.              totalForce x: (totalForce x - forceX).
  790.              totalForce y: (totalForce y - forceY).
  791.              j _ j + 1].
  792.         i _ i + 1].!
  793.  
  794. movePoints
  795.     "Assume that forceVector has been computed. Move each point in response to the combined forces on it."
  796.  
  797.     | i delta xMagnitude yMagnitude |
  798.     maxForce _ 0.0.
  799.     i _ 1.
  800.     [i <= vertexCount] whileTrue:
  801.         [delta _ forces at: i.
  802.          (vertices at: i) moveBy: delta.
  803.  
  804.          xMagnitude _ delta x.
  805.          (xMagnitude < 0.0) ifTrue:
  806.             [xMagnitude _ xMagnitude negated].
  807.          (xMagnitude > maxForce) ifTrue:
  808.             [maxForce _ xMagnitude].
  809.  
  810.          yMagnitude _ delta y.
  811.          (yMagnitude < 0.0) ifTrue:
  812.             [yMagnitude _ yMagnitude negated].
  813.          (yMagnitude > maxForce) ifTrue:
  814.             [maxForce _ yMagnitude].
  815.          i _ i + 1].!
  816.  
  817. solve
  818.  
  819.     | v |
  820.     maxForce _ 10.0.        "ensure that loop is executed once"
  821.     [maxForce > 0.1] whileTrue:
  822.         [self computeForces.
  823.          self movePoints].
  824.     self updateGlyphs.! !
  825.  
  826. !GraphLayout methodsFor: 'animation'!
  827.  
  828. doStep
  829.     "Do one solution step and answer true if we are done."
  830.  
  831.     self computeForces.
  832.     self movePoints.
  833.     self updateGlyphs.
  834.     ^maxForce < 0.1!
  835.  
  836. updateGlyphs
  837.     "Update all the glyphs pointed to by entries in the vertex table."
  838.  
  839.     vertices do:
  840.         [: v | v location: (v x rounded@v y rounded)].!
  841.  
  842. updateVertices
  843.     "Update all the vertices from their glyphs if the glyphs have moved."
  844.  
  845.     vertices do:
  846.         [: v |
  847.          (v x rounded = v location x) ifFalse:
  848.             [v x: v location x].
  849.          (v y rounded = v location y) ifFalse:
  850.             [v y: v location y]].! !
  851.  
  852. BitEditor subclass: #NotifyingBitEditor
  853.     instanceVariableNames: 'client doneFlag '
  854.     classVariableNames: ''
  855.     poolDictionaries: ''
  856.     category: 'ThingLabII-UI-Support'!
  857.  
  858.  
  859. !NotifyingBitEditor methodsFor: 'menu messages'!
  860.  
  861. accept
  862.     "The edited information should now be accepted by the view."
  863.  
  864.     view accept.
  865.     (client notNil) ifTrue: [client acceptChange].!
  866.  
  867. cancel
  868.     "The undo all edits (since the last accept)."
  869.  
  870.     super cancel.!
  871.  
  872. clear
  873.     "Clear my form."
  874.  
  875.     view workingForm white.
  876.     view displayView.!
  877.  
  878. close
  879.     "Close this bit editor without accepting the edits."
  880.  
  881.     (client notNil) ifTrue: [client doneEditing].
  882.     doneFlag _ true.    "make controller let go..."
  883.     view topView controller close.!
  884.  
  885. collapse
  886.  
  887.     view topView controller collapse.!
  888.  
  889. done
  890.     "Accept the edited bitmap and close this bit editor."
  891.  
  892.     self accept.
  893.     (client notNil) ifTrue: [client doneEditing].
  894.     doneFlag _ true.    "make controller let go..."
  895.     view topView controller close.!
  896.  
  897. move
  898.  
  899.     view topView controller move.!
  900.  
  901. newLabel
  902.  
  903.     view topView controller newLabel.!
  904.  
  905. under
  906.  
  907.     view topView controller under.! !
  908.  
  909. !NotifyingBitEditor methodsFor: 'private'!
  910.  
  911. client: anObject
  912.  
  913.     doneFlag _ false.
  914.     client _ anObject.!
  915.  
  916. initializeYellowButtonMenu
  917.  
  918.     self
  919.         yellowButtonMenu:
  920.             (PopUpMenu
  921.                 labels: 'clear\accept\cancel\done' withCRs
  922.                 lines: #(1))
  923.         yellowButtonMessages:
  924.             #(clear accept cancel done).
  925.     self
  926.         blueButtonMenu:
  927.             (PopUpMenu
  928.                 labels: 'new label\under\move\collapse\close' withCRs
  929.                 lines: #(1 4))
  930.         blueButtonMessages:
  931.             #(newLabel under move collapse close).!
  932.  
  933. isControlActive
  934.  
  935.     ^self viewHasCursor
  936.         & sensor keyboardPressed not
  937.         & doneFlag not! !
  938. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  939.  
  940. NotifyingBitEditor class
  941.     instanceVariableNames: ''!
  942.  
  943.  
  944. !NotifyingBitEditor class methodsFor: 'instance creation'!
  945.  
  946. installClient: client in: aScheduledView
  947.  
  948.     aScheduledView subViews do: [: v |
  949.         (v controller isMemberOf: self)
  950.             ifTrue: [v controller client: client]].!
  951.  
  952. openOnForm: aForm at: magnifiedLocation scale: scaleFactor notify: client
  953.     "Create and schedule a BitEditor on the form aForm. Show the small and  magnified view of aForm."
  954.  
  955.     | aScheduledView |
  956.     aScheduledView _ self
  957.         bitEdit: aForm
  958.         at: magnifiedLocation
  959.         scale: scaleFactor
  960.         remoteView: nil.
  961.     self installClient: client in: aScheduledView.
  962.     (aScheduledView controller)
  963.         blueButtonMenu: nil blueButtonMessages: nil.
  964.     aScheduledView controller openDisplayAt:
  965.         aScheduledView displayBox topLeft +
  966.             (aScheduledView displayBox extent / 2)!
  967.  
  968. openOnForm: aForm client: client
  969.  
  970.     | scaleFactor |
  971.     scaleFactor _ 4@4.
  972.     self openOnForm: aForm
  973.         at: (self locateMagnifiedView: aForm scale: scaleFactor) topLeft
  974.         scale:scaleFactor
  975.         notify: client.! !
  976.  
  977. Object subclass: #WalkEquation
  978.     instanceVariableNames: 'constant vars '
  979.     classVariableNames: ''
  980.     poolDictionaries: ''
  981.     category: 'ThingLabII-Module Compiler'!
  982. WalkEquation comment:
  983. 'I represent a walkabout strength equation of the form:
  984.     (((constant weakest: a) weakest: b) weakest: c)
  985. where a, b, and c are references to variables whose strength will not be known until run-time. I fold constant terms as I am created.
  986.  
  987. Strength cooperates with me by turning expressesions of the form:
  988.     aStrength weakest: aWalkEquation
  989. into:
  990.     aWalkEquation weakest: aStrength
  991. so that I respond with a new WalkEquation.'!
  992.  
  993.  
  994. !WalkEquation methodsFor: 'initialize-release'!
  995.  
  996. constant: aStrength vars: varList
  997.  
  998.     constant _ aStrength.
  999.     vars _ varList.! !
  1000.  
  1001. !WalkEquation methodsFor: 'access'!
  1002.  
  1003. constant
  1004.     "Answer the constant part of me."
  1005.  
  1006.     ^constant!
  1007.  
  1008. vars
  1009.     "Answer my variable list."
  1010.  
  1011.     ^vars! !
  1012.  
  1013. !WalkEquation methodsFor: 'operations'!
  1014.  
  1015. sameAs: aStrength
  1016.     "Answer true if I am constant and I am equal to the given strength."
  1017.  
  1018.     (constant isNil | vars isEmpty not) ifTrue: [^false].
  1019.     ^constant sameAs: aStrength!
  1020.  
  1021. simplify
  1022.     "Remove redundant 'required' constant. That is, if my constant part is 'required' and my vars list is not empty, the constant part can be omitted since 'required' is the upper bound on constraint strengths anyway."
  1023.  
  1024.     ((constant notNil) and:
  1025.      [(constant sameAs: Strength required) & (vars isEmpty not)]) ifTrue:
  1026.         [constant _ nil].!
  1027.  
  1028. strongest: strengthOrEquation
  1029.     "Answer a new WalkEquation that is the maximum of myself and the given Strength or WalkEquation."
  1030.  
  1031.     | constPart |
  1032.     (strengthOrEquation isMemberOf: Strength)
  1033.         ifTrue:    "it's a Strength"
  1034.             [^WalkEquation
  1035.                 constant:
  1036.                     ((constant isNil)
  1037.                         ifTrue: [strengthOrEquation]
  1038.                         ifFalse: [self constant strongest: strengthOrEquation])
  1039.                 vars: self vars]
  1040.         ifFalse:    "it's another WalkEquation"
  1041.             [constPart _
  1042.                 (self constant isNil)
  1043.                     ifTrue: [strengthOrEquation constant]    "mine is nil, use his"
  1044.                     ifFalse:
  1045.                         [(strengthOrEquation constant isNil)
  1046.                             ifTrue: [self constant]            "his is nil, use mine"
  1047.                             ifFalse:                     "neither is nil, so combine"
  1048.                                 [self constant strongest:
  1049.                                         strengthOrEquation constant]].
  1050.              ^WalkEquation
  1051.                 constant: constPart
  1052.                 vars: (self vars, strengthOrEquation vars)]!
  1053.  
  1054. weakest: strengthOrEquation
  1055.     "Answer a new WalkEquation that is the minimum of myself and the given Strength or WalkEquation."
  1056.  
  1057.     | constPart |
  1058.     (strengthOrEquation isMemberOf: Strength)
  1059.         ifTrue:    "it's a Strength"
  1060.             [^WalkEquation
  1061.                 constant:
  1062.                     ((constant isNil)
  1063.                         ifTrue: [strengthOrEquation]
  1064.                         ifFalse: [self constant weakest: strengthOrEquation])
  1065.                 vars: self vars]
  1066.         ifFalse:    "it's another WalkEquation"
  1067.             [constPart _
  1068.                 (self constant isNil)
  1069.                     ifTrue: [strengthOrEquation constant]    "mine is nil, use his"
  1070.                     ifFalse:
  1071.                         [(strengthOrEquation constant isNil)
  1072.                             ifTrue: [self constant]            "his is nil, use mine"
  1073.                             ifFalse:                     "neither is nil, so combine"
  1074.                                 [self constant weakest:
  1075.                                         strengthOrEquation constant]].
  1076.              ^WalkEquation
  1077.                 constant: constPart
  1078.                 vars: (self vars, strengthOrEquation vars)]! !
  1079.  
  1080. !WalkEquation methodsFor: 'code generation'!
  1081.  
  1082. putVarExpr: varList on: aStream
  1083.     "Append to the given stream a code string for an expression of the form:
  1084.         (a weakest: (b weakest: (c weakest: (d))))."
  1085.  
  1086.     aStream nextPut: $(.
  1087.     (varList size == 1)
  1088.         ifTrue:
  1089.             [varList first strengthCodeStringOn: aStream]
  1090.         ifFalse:
  1091.             [varList first strengthCodeStringOn: aStream.
  1092.              aStream nextPutAll: ' weakest: '; cr; tab; tab.
  1093.              self putVarExpr: (varList copyFrom: 2 to: varList size) on: aStream].    
  1094.     aStream nextPut: $).!
  1095.  
  1096. storeOn: aStream
  1097.     "Append the code for this walkabout strength equation to the given stream."
  1098.  
  1099.     aStream nextPut: $(.
  1100.     "store the constant part if it exists and is not an unneeded 'required'"
  1101.     (constant notNil) ifTrue:
  1102.         [constant storeOn: aStream.
  1103.          (vars isEmpty) ifFalse:
  1104.             [aStream nextPutAll: ' weakest: '; cr; tab;tab]].
  1105.     self putVarExpr: vars on: aStream.
  1106.     aStream nextPut: $).! !
  1107.  
  1108. !WalkEquation methodsFor: 'printing'!
  1109.  
  1110. printOn: aStream
  1111.  
  1112.     aStream nextPutAll: 'WEqn('.
  1113.     (constant notNil) ifTrue:
  1114.         [constant printOn: aStream.
  1115.          aStream nextPutAll: ' min: '].
  1116.     vars do:
  1117.         [: v |
  1118.          v printOn: aStream.
  1119.          aStream nextPutAll: ' min: '].
  1120.     (constant notNil | vars isEmpty not) ifTrue:
  1121.         [aStream skip: -6].
  1122.     aStream nextPutAll: ')'.! !
  1123. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1124.  
  1125. WalkEquation class
  1126.     instanceVariableNames: ''!
  1127.  
  1128.  
  1129. !WalkEquation class methodsFor: 'instance creation'!
  1130.  
  1131. constant: aSymbol
  1132.  
  1133.     ^self new
  1134.         constant: (Strength of: aSymbol)
  1135.         vars: OrderedCollection new!
  1136.  
  1137. constant: aStrength vars: varList
  1138.  
  1139.     ^self new
  1140.         constant: aStrength
  1141.         vars: varList!
  1142.  
  1143. external: aVariable
  1144.  
  1145.     ^self new
  1146.         constant: nil
  1147.         vars: (OrderedCollection with: aVariable)! !
  1148.  
  1149. Object subclass: #DebugPartitionRecord
  1150.     instanceVariableNames: 'constraintRecords solver solutionIndex neverLaidOut cycleFlag '
  1151.     classVariableNames: ''
  1152.     poolDictionaries: ''
  1153.     category: 'ThingLabII-UI-Debugger'!
  1154. DebugPartitionRecord comment:
  1155. 'This class describes a partition of the constraint graph being debugged. It consists of a collection of DebugConstraintRecords, a constraint solver, and a GraphLayout object for the partition.'!
  1156.  
  1157.  
  1158. !DebugPartitionRecord methodsFor: 'accessing'!
  1159.  
  1160. constraintRecords
  1161.  
  1162.     ^constraintRecords!
  1163.  
  1164. constraintRecords: aCollectionOfConstraintRecords
  1165.  
  1166.     neverLaidOut _ true.
  1167.     constraintRecords _ aCollectionOfConstraintRecords.!
  1168.  
  1169. neverLaidOut
  1170.  
  1171.     ^neverLaidOut!
  1172.  
  1173. solution
  1174.     "Zero is the current solution. Positive integers are alternative possible solutions."
  1175.  
  1176.     ^solutionIndex - 1!
  1177.  
  1178. solution: aNumber
  1179.     "Zero is the current solution. Positive integers are alternative possible solutions."
  1180.  
  1181.     solutionIndex _ aNumber + 1.
  1182.     self updateGlyphs.
  1183.     self setCycleFlag.!
  1184.  
  1185. solver
  1186.  
  1187.     ^solver!
  1188.  
  1189. solver: aMultiSolver
  1190.  
  1191.     solver _ aMultiSolver.! !
  1192.  
  1193. !DebugPartitionRecord methodsFor: 'operations'!
  1194.  
  1195. animateOn: aView
  1196.     "Animate the placement algorithm."
  1197.  
  1198.     | layoutTool done |
  1199.     layoutTool _ self graphLayoutTool.
  1200.     layoutTool updateVertices.
  1201.     done _ false.
  1202.     [done | Sensor anyButtonPressed] whileFalse:
  1203.         [done _ layoutTool doStep.
  1204.          self centerConstraints.
  1205.          aView displaySafe: [aView displayScene]].!
  1206.  
  1207. centerConstraints
  1208.     "Center the constraints of this partition."
  1209.  
  1210.     | centerOfGraph |
  1211.     centerOfGraph _
  1212.         (constraintRecords inject: 0@0 into: [: sum : c | sum + c glyph location]) //
  1213.             (constraintRecords size).
  1214.     constraintRecords do:
  1215.         [: cRec | cRec centerConstraint: centerOfGraph].!
  1216.  
  1217. findAllSolutions
  1218.     "This can be very expensive for large partitions!! Find and record all the possible solutions for this partition so that the user may browse through them."
  1219.  
  1220.     | allSolutions cRec solutions |
  1221.     allSolutions _ solver computeSolutions; allSolutions.
  1222.     1 to: constraintRecords size do:
  1223.         [: constraintIndex |
  1224.          cRec _ constraintRecords at: constraintIndex.
  1225.          solutions _ allSolutions collect: [: methods | methods at: constraintIndex].
  1226.          solutions addFirst: cRec solutions first.    "remember the current solution"
  1227.          cRec solutions: solutions].!
  1228.  
  1229. graphLayoutTool
  1230.  
  1231.     | vertices transitions constraintVars n i j |
  1232.     vertices _ IdentitySet new: 40.
  1233.     constraintRecords do:
  1234.         [: cRec | vertices addAll: cRec varGlyphs].
  1235.     vertices _ vertices asOrderedCollection.
  1236.     transitions _ (Matrix square: vertices size) fill: 1000.    "infinite distance"
  1237.     1 to: vertices size do:
  1238.         [: i |
  1239.          (vertices at: i) label: i.
  1240.          transitions row: i col: i put: 0].                    "zero distance from i to i"
  1241.     constraintRecords do:
  1242.         [: cRec |
  1243.          constraintVars _ cRec varGlyphs.
  1244.          n _ constraintVars size.
  1245.          1 to: (n - 1) do:
  1246.             [: v1 |
  1247.              i _ (constraintVars at: v1) label.
  1248.              (v1 + 1) to: n do:
  1249.                 [: v2 |
  1250.                  j _ (constraintVars at: v2) label.
  1251.                  "distance of one between each pair of vertices joined by a constraint"
  1252.                  transitions row: i col: j put: 1.
  1253.                  transitions row: j col: i put: 1]]].
  1254.  
  1255.     ^GraphLayout new vertices: vertices transitions: transitions!
  1256.  
  1257. initialLayout
  1258.     "Construct an initial layout of the graph."
  1259.  
  1260.     | layoutTool done |
  1261.     layoutTool _ self graphLayoutTool.
  1262.     2 timesRepeat: [layoutTool doStep].
  1263.     self centerConstraints.
  1264.     neverLaidOut _ false.!
  1265.  
  1266. setCycleFlag
  1267.     "Set the cycleFlag if the current solution has a cycle."
  1268.  
  1269.     | methodList method |
  1270.     methodList _ OrderedCollection new: 100.
  1271.     constraintRecords do:
  1272.         [: cRec |
  1273.          method _ cRec solutions at: solutionIndex.
  1274.          methodList add: method].
  1275.     cycleFlag _ solver hasCycle: methodList.!
  1276.  
  1277. solutionCount
  1278.     "Answer the number of possible alternate solutions for this partition."
  1279.     "Detail: The first solution in the solutions list is the current solution, which we don't count."
  1280.  
  1281.     ^constraintRecords first solutions size - 1!
  1282.  
  1283. solutionHasCycle
  1284.     "Answer true if the current solution has a cycle."
  1285.  
  1286.     ^cycleFlag!
  1287.  
  1288. toggleLabels
  1289.     "Toggle the visibility of the constraint labels of this partition."
  1290.  
  1291.     (constraintRecords first glyph labelIsHidden)
  1292.         ifTrue: [constraintRecords do: [: c | c glyph showLabel]]
  1293.         ifFalse: [constraintRecords do: [: c | c glyph hideLabel]].!
  1294.  
  1295. updateCurrentSolution
  1296.     "Update the current solution."
  1297.  
  1298.     constraintRecords do:
  1299.         [: cRec | cRec updateCurrentSolution].!
  1300.  
  1301. updateGlyphs
  1302.     "Update the constraint glyphs to reflect the selected solution."
  1303.  
  1304.     constraintRecords do:
  1305.         [: cRec | cRec updateGlyph: solutionIndex].! !
  1306.  
  1307. Object subclass: #TranslationRule
  1308.     instanceVariableNames: 'from to '
  1309.     classVariableNames: ''
  1310.     poolDictionaries: ''
  1311.     category: 'ThingLabII-Equations'!
  1312. TranslationRule comment:
  1313. 'I am a replacement rule for transforming one parse tree with another. I consists of two parse trees representing patterns, a "from" tree and a "to" tree. The variables in these parse trees represent arbitrary subtrees.
  1314.  
  1315. I am used by finding an instance of me whose "from" tree matches the target parse tree. This transformation rule is then "applied" by filling in a copy of its "to" tree with the subtrees of the target parse tree corresponding to the variables of the "from" tree and answering the resulting parse tree.
  1316. '!
  1317.  
  1318.  
  1319. !TranslationRule methodsFor: 'initialization'!
  1320.  
  1321. from: fromString to: toString
  1322.     "Create parse trees for the expressions represented by my arguments. Verify that the output pattern does not reference any variable that was not part of the input pattern. It is permissible to leave one or more input variables out of the output pattern, although such a transform will naturally lose information."
  1323.  
  1324.     | parseTree fromVars toVars |
  1325.     parseTree _ EquationParser parse: ('dummy ', fromString) readStream.
  1326.     from _ parseTree block statements first.
  1327.     parseTree _ EquationParser parse: ('dummy ', toString) readStream.
  1328.     to _ parseTree block statements first.
  1329.  
  1330.     "check for output vars that were not in the input pattern"
  1331.     fromVars _ from allVariables.
  1332.     toVars _ to allVariables.
  1333.     toVars do:
  1334.         [: v |
  1335.          (fromVars includes: v) ifFalse:
  1336.              [self error: 'Equation Tree Mismatch:
  1337. ''from'' tree does not contain variable ''', v, '''']].! !
  1338.  
  1339. !TranslationRule methodsFor: 'match and apply'!
  1340.  
  1341. applyUsing: mappingDict
  1342.     "Apply this rule by making the variable substitutions given by mappingDict in the output side of the rule. mappingDict was build during matching."
  1343.  
  1344.     ^to transformBy:        "transformBy: makes a copy of the tree"
  1345.         [: node |
  1346.          (node isMemberOf: VariableNode)
  1347.             ifTrue: [node mapBy: mappingDict]
  1348.             ifFalse: [node]]!
  1349.  
  1350. matches: targetParseTree
  1351.     "Match the input pattern of this rule against the given parse tree, collecting mappings from variables to subtrees in a dictionary. If the match succeeds, answer the match dictionary. If it fails, answer nil."
  1352.  
  1353.     | matchDict |
  1354.     matchDict _ Dictionary new.
  1355.     ^(from match: targetParseTree using: matchDict)
  1356.         ifTrue: [matchDict]
  1357.         ifFalse: [nil]! !
  1358.  
  1359. !TranslationRule methodsFor: 'printing'!
  1360.  
  1361. printOn: aStream
  1362.  
  1363.     from printOn: aStream.
  1364.     aStream nextPutAll: '-->'.
  1365.     to printOn: aStream.! !
  1366. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1367.  
  1368. TranslationRule class
  1369.     instanceVariableNames: ''!
  1370.  
  1371.  
  1372. !TranslationRule class methodsFor: 'instance creation'!
  1373.  
  1374. from: fromString to: toString
  1375.     "Create parse trees for the expressions represented by my arguments."
  1376.  
  1377.     ^self new from: fromString to: toString! !
  1378.  
  1379. Object subclass: #Matrix
  1380.     instanceVariableNames: 'rows '
  1381.     classVariableNames: ''
  1382.     poolDictionaries: ''
  1383.     category: 'ThingLabII-UI-Layout'!
  1384.  
  1385.  
  1386. !Matrix methodsFor: 'public'!
  1387.  
  1388. col: column
  1389.     "Answer the column with the given index. Column are numbered from 1 to N."
  1390.  
  1391.     ^rows collect: [: row | row at: column]!
  1392.  
  1393. columnCount
  1394.     "Answer the number of columns in this matrix."
  1395.  
  1396.     ^(rows at: 1) size!
  1397.  
  1398. copy
  1399.     "Answer a copy of myself."
  1400.  
  1401.     ^(self class basicNew) setRows: (rows collect: [: row | row copy])!
  1402.  
  1403. fill: aValue
  1404.     "Fill the matrix with the given value."
  1405.  
  1406.     | rowSize |
  1407.     rowSize _ self rowCount.
  1408.     rows _ rows collect: [: ignore | Array new: rowSize withAll: aValue].!
  1409.  
  1410. row: row
  1411.     "Answer the row with the given index. Rows are numbered from 1 to N."
  1412.  
  1413.     ^rows at: row!
  1414.  
  1415. row: row col: column
  1416.     "Answer the element at the given location."
  1417.  
  1418.     ^(rows at: row) at: column!
  1419.  
  1420. row: row col: column put: element
  1421.     "Store the given element at the given location."
  1422.  
  1423.     (rows at: row) at: column put: element.!
  1424.  
  1425. rowCount
  1426.     "Answer the number of rows in this matrix."
  1427.  
  1428.     ^rows size!
  1429.  
  1430. rows
  1431.     "Answer a collection of my rows."
  1432.  
  1433.     ^rows! !
  1434.  
  1435. !Matrix methodsFor: 'printing'!
  1436.  
  1437. printOn: aStream
  1438.  
  1439.     aStream nextPut: $[.
  1440.     rows do:
  1441.         [: row |
  1442.          row printOn: aStream.
  1443.          aStream cr].
  1444.     aStream skip: -1.
  1445.     aStream nextPut: $].! !
  1446.  
  1447. !Matrix methodsFor: 'private'!
  1448.  
  1449. initialRows: rowCount columns: columnCount
  1450.     "Make an empty matix with the given number of rows and columns."
  1451.  
  1452.     rows _ (1 to: rowCount) collect:
  1453.                 [: row | Array new: columnCount].!
  1454.  
  1455. setRows: arrayOfRows
  1456.     "Replace my rows with the given array of rows. Used by copy."
  1457.  
  1458.     rows _ arrayOfRows.! !
  1459. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1460.  
  1461. Matrix class
  1462.     instanceVariableNames: ''!
  1463.  
  1464.  
  1465. !Matrix class methodsFor: 'instance creation'!
  1466.  
  1467. rows: rowCount columns: columnCount
  1468.     "Answer a Matrix with the given numbers of rows and columns, initially filled with nils."
  1469.  
  1470.     ^(self basicNew) initialRows: rowCount columns: columnCount!
  1471.  
  1472. square: size
  1473.     "Answer a square Matrix with 'size' rows and columns, initially filled with nils."
  1474.  
  1475.     ^(self basicNew) initialRows: size columns: size! !
  1476.  
  1477. Object subclass: #ModulePartition
  1478.     instanceVariableNames: 'id constraints varTable solutions '
  1479.     classVariableNames: ''
  1480.     poolDictionaries: ''
  1481.     category: 'ThingLabII-Module Compiler'!
  1482. ModulePartition comment:
  1483. 'A ThingPartition is used during module compilation to keep track of the possible solutions for a given partition of the constraint graph. Each partition is eventually compiled into a ModuleConstraint.
  1484.  
  1485.     id            <Integer>    unique id for this partition
  1486.     constraints    {Constraint}    the constraints for this partition
  1487.     solutions        {{method}}    the solutions for this parition
  1488.                             (a solution is a set of methods)
  1489.     varType        <Dictionary>    maps each variable (a ThingData) to one of:
  1490.                     #external    -- the variable is an external part
  1491.                     #internal    -- the variable is an internal part
  1492.                     #temporary    -- the variable does not hold state
  1493.                                     between calls to the satisfier'!
  1494.  
  1495.  
  1496. !ModulePartition methodsFor: 'initialize-release'!
  1497.  
  1498. on: constraintList
  1499.     "Initialize this instance with the given constraints."
  1500.  
  1501.     constraints _ constraintList.
  1502.     id _ nil.            "filled in later"
  1503.     varTable _ nil.    "filled in later"
  1504.     solutions _ nil.    "filled in later"! !
  1505.  
  1506. !ModulePartition methodsFor: 'operations'!
  1507.  
  1508. buildVariableTable
  1509.     "Build a table of all the variables referenced by my constraints."
  1510.     "Details: Due to merges, there may be numerous paths (references) for the same variable. The thingData for all refererences will be the same, however, so we use thingDatas to keep track of the variables that have been recorded in the table."
  1511.  
  1512.     | recordedVars thingData |
  1513.     varTable _ OrderedCollection new.
  1514.     recordedVars _ IdentitySet new: 20.
  1515.     constraints do:
  1516.         [: c |
  1517.          (c variables) do:
  1518.             [: ref |
  1519.              thingData _ ref thingData.
  1520.              (recordedVars includes: thingData) ifFalse:
  1521.                 [varTable add: (ModuleVarTableEntry on: ref).
  1522.                  recordedVars add: thingData]]].!
  1523.  
  1524. computeSolutions
  1525.     "Compute all possible solutions to the constraints in this partition."
  1526.  
  1527.     | extVars |
  1528.     extVars _ OrderedCollection new: varTable size.
  1529.     varTable do:
  1530.         [: entry |
  1531.          (entry isExternal) ifTrue:
  1532.             [extVars add: entry thingData]].
  1533.     solutions _
  1534.         (MultiSolver solutionsFor: constraints externalVars: extVars) collect:
  1535.             [: s | ModuleSolution on: s].!
  1536.  
  1537. declareExternalVars: externalRefs
  1538.     "Build the variable table and identify the external variables."
  1539.  
  1540.     | ref |
  1541.     self buildVariableTable.
  1542.     varTable do:
  1543.         [: entry |
  1544.          ref _ externalRefs
  1545.             detect: [: ref | ref thingData == entry thingData]
  1546.             ifNone: [nil].
  1547.          (ref notNil) ifTrue:
  1548.             [entry makeExternal: ref]].!
  1549.  
  1550. hasExternalVars
  1551.     "Answer true if this partition has at least one external variable."
  1552.  
  1553.     varTable do:
  1554.         [: entry | (entry isExternal) ifTrue: [^true]].
  1555.     ^false    "has only no external variables"!
  1556.  
  1557. initializeInternalVarsFor: newModule
  1558.     "Initialize the internal variables for the new Module."
  1559.  
  1560.     | instIndex |
  1561.     varTable do:
  1562.         [: var |
  1563.          (var isInternal) ifTrue:
  1564.             [instIndex _ newModule class instVarNames indexOf: var name.
  1565.              instIndex _ instIndex + newModule class superclass instOffset.
  1566.              newModule instVarAt: instIndex put: var value]].!
  1567.  
  1568. isEmpty
  1569.     "Answer true if I contain no constraints."
  1570.  
  1571.     ^constraints isEmpty!
  1572.  
  1573. removeExternalPartConstraints: externalConstraints
  1574.     "Remove all constraints that appear in the given list. This method is used to remove constraints owned by external parts."
  1575.  
  1576.     constraints _ constraints select:
  1577.         [: c | (externalConstraints includes: c) not].!
  1578.  
  1579. setID: aNumber
  1580.     "Set the ID of this partition."
  1581.  
  1582.     id _ aNumber.! !
  1583.  
  1584. !ModulePartition methodsFor: 'analysis'!
  1585.  
  1586. analyzeSolutions
  1587.     "Process all the solutions, computing their walkabout strength equations and dependency lists. Filter out any solutions that we don't like."
  1588.  
  1589.     | externalVars newSolutions checkEqn |
  1590.     "build a dictionary of external variables for use with currentDependencies:"
  1591.     externalVars _ IdentityDictionary new.
  1592.     varTable do:
  1593.         [: var | (var isExternal) ifTrue:
  1594.             [externalVars at: var thingData put: var]].
  1595.  
  1596.     "examine all solutions"
  1597.     newSolutions _ OrderedCollection new: solutions size.
  1598.     solutions do:
  1599.         [: solution |
  1600.          self apply: solution.
  1601.          checkEqn _ self currentIsPossibleEquation.
  1602.          (checkEqn isFalse not & self solutionOkay) ifTrue:
  1603.             [solution isPossibleEquation: checkEqn.
  1604.              solution plan: (self extractPlan).
  1605.              self recordDependencies: externalVars in: solution.
  1606.              newSolutions addLast: solution]].
  1607.  
  1608.     "classify the variables"
  1609.     varTable do: [: var | var classify].
  1610.  
  1611.     solutions _ newSolutions.!
  1612.  
  1613. apply: aSolution
  1614.     "Apply the given solution, computing ancestors and walk strengths. The latter quantity is computed symbolically since we don't know the walkabout strengths of the external variables at compile time."
  1615.  
  1616.     "first, initialize the variables"
  1617.     varTable do:
  1618.         [: entry |
  1619.          (entry isExternal)
  1620.             ifTrue: [entry thingData initExternal: entry]
  1621.             ifFalse: [entry thingData initInternal]].
  1622.  
  1623.     "then, satisfy all constraints using the methods of the given solution"
  1624.     aSolution methods with: constraints do:
  1625.         [: method : constraint |
  1626.          (method isNil)
  1627.             ifTrue: [constraint whichMethod: nil]
  1628.             ifFalse:
  1629.                 [constraint satisfyWith: method.
  1630.                  DeltaBluePlanner
  1631.                     addPropagateFrom: constraint
  1632.                     execFlag: false]].!
  1633.  
  1634. currentIsPossibleEquation
  1635.     "Answer the walkabout strength check equation for the current solution."
  1636.  
  1637.     | walkEqn thingDatas orTerm |
  1638.     walkEqn _ ModuleConjunction new.
  1639.     constraints do:
  1640.         [: c |
  1641.          (c isSatisfied) ifFalse:
  1642.             ["unsatisfied constraints must not demand satisfaction"
  1643.              thingDatas _ c thingDatas.
  1644.              c methods do:
  1645.                 [: m |
  1646.                  orTerm _ ModuleDisjunction new.
  1647.                  m outDatasIn: thingDatas do:
  1648.                      [: v |
  1649.                      orTerm
  1650.                         strength: (c strength)
  1651.                         weakerOrEq: (v walkStrength)].
  1652.                  walkEqn addOrTerm: orTerm]]].
  1653.  
  1654.     "the propagated walk strengths must be strong enough to override their outputs"
  1655.     varTable do:
  1656.         [: entry |
  1657.          (entry isOutput) ifTrue:
  1658.             [walkEqn var: entry weakerOrEq: entry thingData walkStrength]].
  1659.  
  1660.     ^walkEqn!
  1661.  
  1662. extractPlan
  1663.     "Extract a plan for the current solution."
  1664.  
  1665.     | thingDatas |
  1666.     thingDatas _ IdentitySet new: varTable size.
  1667.     varTable do: [: v | thingDatas add: v thingData].
  1668.     ^(DeltaBluePlanner extractPlanFromThingDatas: thingDatas optimizeStays: false)
  1669.         collect: [: c | c whichMethod]!
  1670.  
  1671. recordDependencies: externalVarDict in: aSolution
  1672.     "Record the variable dependencies and walkabout strength equations for all output variables of the current solution. We only record dependencies among the external variables. Also record the status of all variables to help with later classification."
  1673.  
  1674.     | outWalkEqns dependencyList varTD ancestorVars externalAncestor |
  1675.     outWalkEqns _ OrderedCollection new.
  1676.     dependencyList _ OrderedCollection new.
  1677.     varTable do:
  1678.         [: var |
  1679.          var recordCurrentStatus.
  1680.          (var isOutput) ifTrue:
  1681.             [varTD _ var thingData.
  1682.              outWalkEqns add: varTD walkStrength.
  1683.              ancestorVars _ OrderedCollection new.
  1684.              varTD ancestors do:
  1685.                 [: ancestorTD |
  1686.                  externalAncestor _ externalVarDict at: ancestorTD ifAbsent: [nil].
  1687.                  (externalAncestor notNil)
  1688.                     ifTrue: [ancestorVars add: externalAncestor]].
  1689.              dependencyList add:
  1690.                 (ModuleDependency
  1691.                     outVar: var
  1692.                     dependsOn: ancestorVars
  1693.                     stay: varTD stay
  1694.                     stayStrength: varTD walkStrength)]].
  1695.     aSolution dependencies: dependencyList.
  1696.     aSolution outWalkEqns: outWalkEqns.!
  1697.  
  1698. solutionOkay
  1699.     "Answer false if we don't like the currently applied solution. We don't like solutions in which all external variables are outputs having walk strengths of absoluteWeakest."
  1700.  
  1701.     varTable do:
  1702.         [: var |
  1703.          (var isExternal) ifTrue:
  1704.             [(var isOutput) ifFalse: [^true].
  1705.              (var thingData walkStrength sameAs: Strength absoluteWeakest)
  1706.                 ifFalse: [^true]]].
  1707.     ^false! !
  1708.  
  1709. !ModulePartition methodsFor: 'compilation'!
  1710.  
  1711. allocateInternalVariables: lastId
  1712.     "Give my internal variables names like 'internal3' starting with the first id following lastId. Answer the last id that I allocated."
  1713.  
  1714.     | varId |
  1715.     varId _ lastId.
  1716.     varTable do:
  1717.         [: var |
  1718.          (var isInternal) ifTrue:
  1719.             [varId _ varId + 1.
  1720.              var name: 'internal', varId printString]].
  1721.     ^varId!
  1722.  
  1723. compileFor: moduleThing
  1724.     "Compile the isPossible, execute, and propagate methods for each solution of this partition. Add the compiled methods to the class of the given ModuleThing. It is assumed that the class contains instance variables for the external and internal parts."
  1725.  
  1726.     | externalVars methods prefix newConstraint |
  1727.     "set up: name variables and collect the external ones"
  1728.     self nameVars.
  1729.     externalVars _ varTable select: [: v | v isExternal].
  1730.  
  1731.     "build a ModuleMethod for each solution"
  1732.     methods _ OrderedCollection new: solutions size.
  1733.     prefix _ 'p', id printString.
  1734.     1 to: solutions size do:
  1735.         [: solutionIndex |
  1736.          BusyCursor inc.
  1737.          methods add:
  1738.             ((solutions at: solutionIndex)
  1739.                 methodFor: moduleThing
  1740.                 namePrefix: (prefix, 'm', solutionIndex printString)
  1741.                 constraints: constraints
  1742.                 externalVars: externalVars
  1743.                 varTable: varTable)].
  1744.  
  1745.     "construct and bind the new Module constraint"
  1746.     newConstraint _ Constraint
  1747.         symbols: (externalVars collect: [: v | v name])
  1748.         methods: methods.
  1749.     newConstraint
  1750.         bind: (externalVars collect: [: v | (v reference) root: moduleThing])
  1751.         strength: #required.
  1752.  
  1753.     "answer the newly created Module constraint"
  1754.     ^newConstraint!
  1755.  
  1756. nameVars
  1757.     "Name all my non-internal variables for use during compilation. This must be done after variable classification. The internal variables are named separately using allocateInternalVariables:."
  1758.  
  1759.     | externals constants temps |
  1760.     externals _ constants _ temps _ 0.
  1761.     varTable do:
  1762.         [: var |
  1763.          (var isExternal) ifTrue:
  1764.             [externals _ externals + 1.
  1765.              var name: 'v', externals printString].
  1766.          (var isConstant) ifTrue:
  1767.             [constants _ constants + 1.
  1768.              var name: 'c', constants printString].
  1769.          (var isTemporary) ifTrue:
  1770.             [temps _ temps + 1.
  1771.              var name: 't', temps printString]].! !
  1772.  
  1773. !ModulePartition methodsFor: 'printing'!
  1774.  
  1775. printOn: aStream
  1776.  
  1777.     aStream cr; nextPutAll: 'ModulePartition('.
  1778.     aStream nextPutAll: constraints size printString.
  1779.     ((constraints size = 0) | (constraints size > 1))
  1780.         ifTrue: [aStream nextPutAll: ' constraints, ']
  1781.         ifFalse: [aStream nextPutAll: ' constraint, '].
  1782.     aStream nextPutAll: solutions size printString.
  1783.     ((solutions size = 0) | (solutions size > 1))
  1784.         ifTrue: [aStream nextPutAll: ' solutions)']
  1785.         ifFalse: [aStream nextPutAll: ' solution)'].! !
  1786. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1787.  
  1788. ModulePartition class
  1789.     instanceVariableNames: ''!
  1790.  
  1791.  
  1792. !ModulePartition class methodsFor: 'instance creation'!
  1793.  
  1794. on: constraintList
  1795.     "Create a new instance of me on the given collection of constraints."
  1796.  
  1797.     ^self new on: constraintList! !
  1798.  
  1799. Collection subclass: #PriorityQueue
  1800.     instanceVariableNames: 'contents last '
  1801.     classVariableNames: ''
  1802.     poolDictionaries: ''
  1803.     category: 'ThingLabII-UI-Layout'!
  1804.  
  1805.  
  1806. !PriorityQueue methodsFor: 'public'!
  1807.  
  1808. add: newElement
  1809.     "Insert the given element in the receiver at the proper location."
  1810.  
  1811.     (contents size == last) ifTrue:
  1812.         ["queue is full, so double the size of 'contents' to make room"
  1813.          contents _ contents, (Array new: last)].
  1814.     last _ last + 1.
  1815.     contents at: last put: newElement.
  1816.     newElement index: last.
  1817.     self pushUpFrom: last.!
  1818.  
  1819. comment
  1820.     "The elements of a PriorityQueue must repond to the messages 'index:' and 'index'. The 'index:' message may be a noop but the 'index' message must either answer the last value provided to the element via the 'index:' message or else nil. This behavior is necessary to allow fast relocation of elements when their priorities change."!
  1821.  
  1822. do: aBlock
  1823.     "Evaluate aBlock with each of the receiver's elements as the argument."
  1824.  
  1825.     | i |
  1826.     i _ 1.
  1827.     [i <= last] whileTrue:
  1828.         [aBlock value: (contents at: i).
  1829.          i _ i + 1].!
  1830.  
  1831. peekMin
  1832.     "Answer the least element of the receiver without removing it."
  1833.  
  1834.     (last == 0) ifTrue: [^self errorEmptyCollection].
  1835.     "The root is the smallest element."
  1836.     ^contents at: 1!
  1837.  
  1838. relocate: targetElement
  1839.     "Find a new position for the given element after it has changed."
  1840.  
  1841.     | target parent leftChild |
  1842.     target _ targetElement index.
  1843.     (target == nil) ifTrue:
  1844.         [target _ self indexOfOrNil: targetElement.
  1845.          (target == nil) ifTrue: [^self]].
  1846.  
  1847.     parent _ target bitShift: -1.
  1848.     (parent == 0)
  1849.         ifTrue: ["target is the root; it has no parent"]
  1850.         ifFalse:
  1851.             [(targetElement < (contents at: parent)) ifTrue:
  1852.                 ["target smaller than parent, push up"
  1853.                  ^self pushUpFrom: target]].
  1854.  
  1855.     leftChild _ target bitShift: 1.
  1856.     (leftChild <= last)
  1857.         ifFalse: ["target is a leaf; it has no children"]
  1858.         ifTrue:
  1859.             [(targetElement > (contents at: leftChild)) ifTrue:
  1860.                 ["target larger than left child, push down"
  1861.                  self pushDownFrom: target].
  1862.              (leftChild ~~ last) ifTrue:
  1863.                 [(targetElement > (contents at: leftChild + 1)) ifTrue:
  1864.                     ["target has, and is larger than, right child, push down"
  1865.                      self pushDownFrom: target]]]
  1866.  
  1867.     "if we get here, then targetElement did not need to move"!
  1868.  
  1869. remove: oldObject ifAbsent: anExceptionBlock
  1870.  
  1871.     self shouldNotImplement.!
  1872.  
  1873. removeAll
  1874.     "Make the receiver empty."
  1875.  
  1876.     last _ 0.!
  1877.  
  1878. removeMin
  1879.     "Remove and answer the least element of the receiver."
  1880.  
  1881.     | smallest oldLast |
  1882.     (last == 0) ifTrue: [^self errorEmptyCollection].
  1883.  
  1884.     "The root is the smallest element."
  1885.     smallest _ contents at: 1.
  1886.  
  1887.     "Remove the last element and replace the root it. Then push it down."
  1888.     oldLast _ contents at: last.
  1889.     contents at: last put: nil.
  1890.     last _ last - 1.
  1891.     contents at: 1 put: oldLast.
  1892.     oldLast index: 1.
  1893.     self pushDownFrom: 1.
  1894.     ^smallest!
  1895.  
  1896. size
  1897.     "Answer how many elements the receiver contains."
  1898.  
  1899.     ^last! !
  1900.  
  1901. !PriorityQueue methodsFor: 'private'!
  1902.  
  1903. indexOfOrNil: anElement
  1904.     "Answer the index of the given element or nil if it is not in the receiver."
  1905.  
  1906.     | i |
  1907.     i _ 1.
  1908.     [i <= last] whileTrue:
  1909.         [((contents at: i) == anElement) ifTrue: [^i].
  1910.          i _ i + 1].
  1911.     ^nil!
  1912.  
  1913. initialize: initialSize
  1914.     "Allocate initial space for the given number of elements."
  1915.  
  1916.     contents _ Array new: initialSize.
  1917.     last _ 0.!
  1918.  
  1919. initializeWithVertices: vertexList except: vertexIndex cost: initialCost
  1920.     "Special add function for support of ShortestPaths. The receiver is first emptied, then all the elements of the given collection except the vertex with the given index are added without regard to order. The elements are given the specified initial cost."
  1921.  
  1922.     | count i element |
  1923.     count _ vertexList size.
  1924.     (contents size < count) ifTrue:
  1925.         [contents _ Array new: count].
  1926.     last _ 0.
  1927.     i _ 1.
  1928.     [i <= count] whileTrue:
  1929.         [(i == vertexIndex) ifFalse:
  1930.             [element _ vertexList at: i.
  1931.               last _ last + 1.
  1932.              contents at: last put: element.
  1933.               element index: last.
  1934.              element cost: initialCost].
  1935.          i _ i + 1].!
  1936.  
  1937. pushDownFrom: index
  1938.     "Push the element at index i down through the tree until it is smaller than its children or until it is a leaf with no children."
  1939.  
  1940.     | leaves parent left right child parentElement childElement |
  1941.     leaves _ last bitShift: -1.
  1942.     parent _ index.
  1943.     [parent <= leaves] whileTrue:    "while parent is not a leaf:"
  1944.         [left _ parent bitShift: 1.
  1945.          right _ left + 1.
  1946.          (left == last)
  1947.             ifTrue:
  1948.                 ["left is an only-child"
  1949.                  child _ left]
  1950.             ifFalse:
  1951.                  ["select the smaller child"
  1952.                  ((contents at: left) < (contents at: right))
  1953.                     ifTrue: [child _ left]
  1954.                     ifFalse: [child _ right]].
  1955.          parentElement _ contents at: parent.
  1956.          childElement _ contents at: child.
  1957.          (parentElement > childElement)
  1958.             ifTrue:
  1959.                 ["push to next level"
  1960.                  contents at: parent put: childElement.
  1961.                  childElement index: parent.
  1962.                  contents at: child put: parentElement.
  1963.                  parentElement index: child.
  1964.                  parent _ child]
  1965.             ifFalse:
  1966.                 ["parent is smaller than its children; cannot push farther"
  1967.                  ^self]].
  1968.     "pushed all the way to a leaf"
  1969.     ^self!
  1970.  
  1971. pushUpFrom: index
  1972.     "Push the element at the given index up through the tree until it is smaller than its children or until it is the root."
  1973.  
  1974.     | child parent childElement parentElement |
  1975.     child _ index.
  1976.     [(child == 1) ifTrue: [^self].    "child is the root, so it has no parent"
  1977.      parent _ child bitShift: -1.
  1978.      childElement _ contents at: child.
  1979.      parentElement _ contents at: parent.
  1980.      (childElement < parentElement)] whileTrue:
  1981.         [contents at: child put: parentElement.
  1982.          parentElement index: child.
  1983.          contents at: parent put: childElement.
  1984.          childElement index: parent.
  1985.          child _ parent].! !
  1986. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1987.  
  1988. PriorityQueue class
  1989.     instanceVariableNames: ''!
  1990.  
  1991.  
  1992. !PriorityQueue class methodsFor: 'instance creation'!
  1993.  
  1994. new
  1995.     "Answer a new instance of me."
  1996.  
  1997.     ^self new: 10!
  1998.  
  1999. new: aNumber
  2000.     "Answer a new instance with the given initial size."
  2001.  
  2002.     ^self basicNew initialize: aNumber! !
  2003.  
  2004. StringHolder subclass: #ThingDefiner
  2005.     instanceVariableNames: 'client view '
  2006.     classVariableNames: ''
  2007.     poolDictionaries: ''
  2008.     category: 'ThingLabII-Things-Support'!
  2009.  
  2010.  
  2011. !ThingDefiner methodsFor: 'initialize-release'!
  2012.  
  2013. client: clientObject
  2014.     "Register a client object. This client will be updated with the prototype of the newly defined Thing when the user does 'accept'. My initial text is derived from the Thing currently held by the client. The client may be any object the understands the messages #thing and #thing:. If the client object is nil, a new Thing is created but noone is informed."
  2015.  
  2016.     client _ clientObject.
  2017.     (client notNil) ifTrue:
  2018.         [contents _ client thing definitionString].!
  2019.  
  2020. view: aView
  2021.     "Set my view to the given view."
  2022.  
  2023.     view _ aView.! !
  2024.  
  2025. !ThingDefiner methodsFor: 'operation'!
  2026.  
  2027. contents: aString
  2028.     "Define a new Thing based on the text that the user has just 'accepted'. Notify the client, if any, of the new Thing's prototype."
  2029.  
  2030.     | tree thingName partNames parts nonThingPart type newThing |
  2031.     tree _  (EquationParser parse: ('dummy ', aString) readStream)
  2032.                 block statements first.
  2033.     (tree isMemberOf: VariableNode) ifTrue:
  2034.         [thingName _ tree name asSymbol.
  2035.          ((Smalltalk includesKey: thingName) and:
  2036.            [(Smalltalk at: thingName) inheritsFrom: Thing])
  2037.             ifTrue:
  2038.                 [newThing _ (Smalltalk at: thingName) new.
  2039.                  contents _ newThing definitionString.
  2040.                  self changed.
  2041.                  (client notNil) ifTrue:
  2042.                     [client thing: newThing].
  2043.                  ^self]
  2044.             ifFalse:
  2045.                 [^self error: thingName asString, ' is not a Thing']].
  2046.     thingName _ tree receiver name.
  2047.     "get partNames and omit trailing colons"
  2048.     partNames _ tree selector key keywords.
  2049.     partNames _ partNames collect: [: n | n copyFrom: 1 to: n size - 1].
  2050.     "get parts"
  2051.     nonThingPart _ nil.
  2052.     parts _ tree arguments.
  2053.     parts _ parts collect:
  2054.         [: t |
  2055.          type _ t name asSymbol.
  2056.          ((Smalltalk includesKey: type) and:
  2057.            [(Smalltalk at: type) inheritsFrom: Thing])
  2058.             ifTrue: [(Smalltalk at: type) prototype]
  2059.             ifFalse: [nonThingPart]].
  2060.     newThing _ Thing
  2061.         defineNewThingNamed: thingName
  2062.         withParts: partNames
  2063.         toHold: parts.
  2064.     (client notNil) ifTrue:
  2065.         [client thing: newThing].
  2066.     (view notNil) ifTrue:
  2067.         [view model updateCaches.
  2068.          view displaySafe: [view displayView]].!
  2069.  
  2070. open
  2071.     "Open a view for this ThingDefiner. This call does not return."
  2072.     "ThingDefiner open"
  2073.  
  2074.     | thingDefinerView topView |
  2075.     thingDefinerView _ StringHolderView container: self.
  2076.     topView _ SpecialSystemView new.
  2077.     topView borderWidth: 1.
  2078.     topView model: thingDefinerView model.
  2079.     topView addSubView: thingDefinerView.
  2080.     topView label: 'Thing Definer'.
  2081.     topView minimumSize: 100@50.
  2082.     topView icon: (Icon constantNamed: #default).
  2083.     topView controller open! !
  2084. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2085.  
  2086. ThingDefiner class
  2087.     instanceVariableNames: ''!
  2088.  
  2089.  
  2090. !ThingDefiner class methodsFor: 'instance creation'!
  2091.  
  2092. open
  2093.     "Open a new ThingDefiner with no client object or view."
  2094.     "ThingDefiner open"
  2095.  
  2096.     (self new)
  2097.         client: nil;
  2098.         view: nil;
  2099.         open!
  2100.  
  2101. openOn: clientObject view: aView
  2102.     "Open a new ThingDefiner for the given client object. The client should understand the messages #thing and #thing:. The view, if non-nil, is updated after the client is changed."
  2103.  
  2104.     (self new)
  2105.         client: clientObject;
  2106.         view: aView;
  2107.         open! !
  2108.  
  2109. Object subclass: #ModuleDependency
  2110.     instanceVariableNames: 'outVar dependsOn stay stayStrength '
  2111.     classVariableNames: ''
  2112.     poolDictionaries: ''
  2113.     category: 'ThingLabII-Module Compiler'!
  2114. ModuleDependency comment:
  2115. 'I am used to record the input/output relationships between external variables for one solution of one partition during the Module compilation process.'!
  2116.  
  2117.  
  2118. !ModuleDependency methodsFor: 'access'!
  2119.  
  2120. dependsOn
  2121.     "Answer the variables on which outVar depends."
  2122.  
  2123.     ^dependsOn!
  2124.  
  2125. outVar
  2126.     "Answer the output variable of this dependency."
  2127.  
  2128.     ^outVar!
  2129.  
  2130. outVar: aVar dependsOn: varList stay: stayFlag stayStrength: aStrength
  2131.     "Initialize myself with the given values. aVar is dependent on the variables in varList. If stayFlag is true, then the outputs are stay with the given strength. If false, then the output stay flags are must be computed at run time as the logical 'AND' of the input stay flags and the output strengths must be computed by evaluating strength equations."
  2132.  
  2133.     outVar _ aVar.
  2134.     dependsOn _ varList asOrderedCollection copy.
  2135.     stay _ stayFlag.
  2136.     (stay == true)
  2137.         ifTrue: [stayStrength _ aStrength]
  2138.         ifFalse: [stayStrength _ nil].    "stayStrength is undefined if stay is false"!
  2139.  
  2140. stay
  2141.  
  2142.     ^stay!
  2143.  
  2144. strengthString
  2145.     "Answer an expression representing the strength at which I am fixed. This operation should only be called if I answer true to the #stay message."
  2146.  
  2147.     ^stayStrength storeString! !
  2148.  
  2149. !ModuleDependency methodsFor: 'printing'!
  2150.  
  2151. printOn: aStream
  2152.  
  2153.     aStream nextPut: $[.
  2154.     outVar printOn: aStream.
  2155.     aStream nextPutAll: ' depends on: '.
  2156.     dependsOn do:
  2157.         [: var |
  2158.          var printOn: aStream.
  2159.          aStream space].
  2160.     (dependsOn isEmpty) ifFalse: [aStream skip: -1].
  2161.     aStream nextPut: $]; cr.! !
  2162. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2163.  
  2164. ModuleDependency class
  2165.     instanceVariableNames: ''!
  2166.  
  2167.  
  2168. !ModuleDependency class methodsFor: 'instance creation'!
  2169.  
  2170. outVar: aVar dependsOn: varList stay: stayFlag stayStrength: aStrength
  2171.     "Create and answer a new dependency relation."
  2172.  
  2173.     ^(self new)
  2174.         outVar: aVar
  2175.         dependsOn: varList
  2176.         stay: stayFlag
  2177.         stayStrength: aStrength! !
  2178.  
  2179. Object subclass: #Strength
  2180.     instanceVariableNames: 'symbolicValue arithmeticValue '
  2181.     classVariableNames: 'AbsoluteStrongest AbsoluteWeakest Required StrengthConstants StrengthTable '
  2182.     poolDictionaries: ''
  2183.     category: 'ThingLabII'!
  2184. Strength comment:
  2185. 'Strengths are used to measure the relative priority of constraints. The hierarchy of available strengths is determined by the class variable StrengthTable (see my class initialization method). Because Strengths are invariant, references to Strength instances are shared (i.e. all references to "Strength of: #required" point to the same instance). New strengths may be inserted in the strength hierarchy.'!
  2186.  
  2187.  
  2188. !Strength methodsFor: 'comparing'!
  2189.  
  2190. leq: aStrength
  2191.     "This is shorthand for 'notStronger: aStrength' (read 'less-than or equal'). This cryptic message is used to make the code for module method 'isPossible' tests more consise and readable. The code given is equivalent to '(self stronger: strength2) not'."
  2192.  
  2193.     ^arithmeticValue >= aStrength arithmeticValue!
  2194.  
  2195. notStronger: aStrength
  2196.     "Answer true if I am the same or weaker than the given Strength. This code is equivalent to:
  2197.  
  2198.     ^(self stronger: aStrength) not"
  2199.  
  2200.     ^arithmeticValue >= aStrength arithmeticValue!
  2201.  
  2202. sameAs: aStrength
  2203.     "Answer true if I am the same strength as the given Strength."
  2204.  
  2205.     ^arithmeticValue = aStrength arithmeticValue!
  2206.  
  2207. stronger: aStrength
  2208.     "Answer true if I am stronger than the given Strength."
  2209.  
  2210.     ^arithmeticValue < aStrength arithmeticValue!
  2211.  
  2212. weaker: aStrength
  2213.     "Answer true if I am weaker than the given Strength."
  2214.  
  2215.     ^arithmeticValue > aStrength arithmeticValue! !
  2216.  
  2217. !Strength methodsFor: 'max/min'!
  2218.  
  2219. strongest: aStrength
  2220.     "Answer the stronger of myself and aStrength."
  2221.  
  2222.     (aStrength class == WalkEquation) ifTrue:
  2223.         [^aStrength strongest: self].
  2224.  
  2225.     (aStrength stronger: self)
  2226.         ifTrue: [^aStrength]
  2227.         ifFalse: [^self].!
  2228.  
  2229. weakest: aStrength
  2230.     "Answer the weaker of myself and aStrength."
  2231.  
  2232.     (aStrength class == WalkEquation) ifTrue:
  2233.         [^aStrength weakest: self].
  2234.  
  2235.     (aStrength weaker: self)
  2236.         ifTrue: [^aStrength]
  2237.         ifFalse: [^self].! !
  2238.  
  2239. !Strength methodsFor: 'printing'!
  2240.  
  2241. printOn: aStream
  2242.     "Append a string which represents my strength onto aStream."
  2243.  
  2244.     aStream nextPutAll: '%', symbolicValue, '%'.!
  2245.  
  2246. storeOn: aStream
  2247.  
  2248.     aStream nextPutAll: '(Strength of: #', self asSymbol, ')'.! !
  2249.  
  2250. !Strength methodsFor: 'converting'!
  2251.  
  2252. asSymbol
  2253.     "Answer myself as a symbol."
  2254.  
  2255.     ^symbolicValue! !
  2256.  
  2257. !Strength methodsFor: 'private'!
  2258.  
  2259. arithmeticValue
  2260.     "Answer my arithmetic value. Used for comparisons. Note that STRONGER constraints have SMALLER arithmetic values."
  2261.  
  2262.     ^arithmeticValue!
  2263.  
  2264. initializeWith: symVal
  2265.     "Record my symbolic value and reset my arithmetic value."
  2266.  
  2267.     symbolicValue _ symVal.
  2268.     self resetValue.!
  2269.  
  2270. resetValue
  2271.     "Lookup my symbolic value in the StrengthTable and reset my internal value."
  2272.  
  2273.     arithmeticValue _ StrengthTable at: symbolicValue.! !
  2274. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2275.  
  2276. Strength class
  2277.     instanceVariableNames: ''!
  2278.  
  2279.  
  2280. !Strength class methodsFor: 'instance creation'!
  2281.  
  2282. of: aSymbol
  2283.     "Answer an instance with the specified strength."
  2284.  
  2285.     ^StrengthConstants at: aSymbol! !
  2286.  
  2287. !Strength class methodsFor: 'class initialization'!
  2288.  
  2289. initialize
  2290.     "Initialize the symbolic strength table. Fix the internally caches values of all existing instances."
  2291.     "Strength initialize"
  2292.  
  2293.     StrengthTable _ Dictionary new.
  2294.     StrengthTable at: #absoluteStrongest put: -1000.
  2295.     StrengthTable at: #required put: 0.
  2296.     StrengthTable at: #strongPreferred put: 1.
  2297.     StrengthTable at: #preferred put: 2.
  2298.     StrengthTable at: #strongDefault put: 3.
  2299.     StrengthTable at: #default put: 4.
  2300.     StrengthTable at: #weakDefault put: 5.
  2301.     StrengthTable at: #absoluteWeakest put: 1000.
  2302.  
  2303.     StrengthConstants _ Dictionary new.
  2304.     StrengthTable associations do:
  2305.         [: assoc |
  2306.             StrengthConstants
  2307.                 at: (assoc key)
  2308.                 put: ((super new) initializeWith: (assoc key))].
  2309.  
  2310.     "Fix arithmetic values stored in all instances."
  2311.     Strength allInstancesDo:
  2312.         [: strength | strength resetValue].
  2313.  
  2314.     AbsoluteStrongest _ Strength of: #absoluteStrongest.
  2315.     AbsoluteWeakest _ Strength of: #absoluteWeakest.
  2316.     Required _ Strength of: #required.! !
  2317.  
  2318. !Strength class methodsFor: 'constants'!
  2319.  
  2320. absoluteStrongest
  2321.  
  2322.     ^AbsoluteStrongest!
  2323.  
  2324. absoluteWeakest
  2325.  
  2326.     ^AbsoluteWeakest!
  2327.  
  2328. required
  2329.  
  2330.     ^Required! !
  2331.  
  2332. Object subclass: #NeedToClone
  2333.     instanceVariableNames: 'data '
  2334.     classVariableNames: ''
  2335.     poolDictionaries: ''
  2336.     category: 'ThingLabII-Things'!
  2337. NeedToClone comment:
  2338. 'During cloning, the NeedToClone class is used to mark those instance variables in a Thing that have not yet been cloned. For example, a copy of a Thing is made and then some of the instance variables are replaced by doing:
  2339.  
  2340.     constraints _ (NeedToClone with: constraints).
  2341.  
  2342. This indicates that constraints still needs cloning, and that the old value is available as ''constraints data''.
  2343. '!
  2344.  
  2345.  
  2346. !NeedToClone methodsFor: 'access'!
  2347.  
  2348. data
  2349.  
  2350.     ^data!
  2351.  
  2352. data: anObject
  2353.  
  2354.     data _ anObject.! !
  2355.  
  2356. !NeedToClone methodsFor: 'printing'!
  2357.  
  2358. printOn: aStream
  2359.  
  2360.     aStream nextPutAll: 'NeedToClone('.
  2361.     data printOn: aStream.
  2362.     aStream nextPutAll: ')'! !
  2363. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2364.  
  2365. NeedToClone class
  2366.     instanceVariableNames: ''!
  2367.  
  2368.  
  2369. !NeedToClone class methodsFor: 'instance creation'!
  2370.  
  2371. with: anObject
  2372.  
  2373.     ^self new data: anObject! !
  2374.  
  2375. Object subclass: #Partitioner
  2376.     instanceVariableNames: 'unexamined '
  2377.     classVariableNames: ''
  2378.     poolDictionaries: ''
  2379.     category: 'ThingLabII-Module Compiler'!
  2380. Partitioner comment:
  2381. 'I am used to divide the constraints of a constraint graph into a set of disjoint partitions.'!
  2382.  
  2383.  
  2384. !Partitioner methodsFor: 'public'!
  2385.  
  2386. partition: aThing
  2387.     "Partition all constraints on aThing and its subparts."
  2388.  
  2389.     | thingDatas |
  2390.     thingDatas _ IdentitySet new: 50.
  2391.     aThing allThingDatasInto: thingDatas.
  2392.     ^self partitionThingDatas: thingDatas!
  2393.  
  2394. partitionConstraints: constraints
  2395.     "Similar to partition:, but starts with a set of constraints rather than a Thing."
  2396.  
  2397.     | thingDatas |
  2398.     thingDatas _ IdentitySet new: 50.
  2399.     constraints do:
  2400.         [: c |
  2401.          c variables do:
  2402.             [: v | thingDatas add: v thingData]].
  2403.     ^self partitionThingDatas: thingDatas!
  2404.  
  2405. partitionThingDatas: thingDatas
  2406.     "Partition all constraints on parts of aThing."
  2407.  
  2408.     | mark partitions |
  2409.     mark _ self chooseMark.
  2410.     unexamined _ thingDatas asOrderedCollection.
  2411.     partitions _ OrderedCollection new: 100.
  2412.     [unexamined isEmpty] whileFalse:
  2413.         [partitions addLast: (self extractPartition: mark)].
  2414.     ^partitions! !
  2415.  
  2416. !Partitioner methodsFor: 'private'!
  2417.  
  2418. chooseMark
  2419.     "Select a mark value."
  2420.  
  2421.     ^Time millisecondClockValue max: 1!
  2422.  
  2423. extractPartition: mark
  2424.     "Extract a partition. A partition is a collection of related constraints."
  2425.  
  2426.     | partition toDo td |
  2427.     partition _ IdentitySet new: 50.        "constraints in this partition"
  2428.     toDo _ OrderedCollection new: 50.        "thingDatas to examine further"
  2429.     toDo add: unexamined first.
  2430.     [toDo isEmpty] whileFalse:
  2431.         [td _ toDo removeFirst.
  2432.          (td mark == mark) ifFalse:
  2433.             [unexamined remove: td ifAbsent: [].    "td is in this partition"
  2434.              td mark: mark.
  2435.              td constraints do:
  2436.                 [: c |
  2437.                  partition add: c.
  2438.                  c variables do:
  2439.                     [: ref | toDo add: ref thingData]]]].
  2440.     ^partition asOrderedCollection! !
  2441. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2442.  
  2443. Partitioner class
  2444.     instanceVariableNames: ''!
  2445.  
  2446.  
  2447. !Partitioner class methodsFor: 'general inquiries'!
  2448.  
  2449. partition: aThing
  2450.     "Partition the constraints of the given Thing. Answer a collection of constraint lists, one for each partition. Each constraint of the given Thing will appear in exactly one of the partitions."
  2451.  
  2452.     ^self new partition: aThing! !
  2453.  
  2454. Object subclass: #EquationTranslator
  2455.     instanceVariableNames: 'theEquationTree theVariables '
  2456.     classVariableNames: 'ReorderRules RestructureRules '
  2457.     poolDictionaries: ''
  2458.     category: 'ThingLabII-Equations'!
  2459.  
  2460.  
  2461. !EquationTranslator methodsFor: 'public access'!
  2462.  
  2463. computeMethods
  2464.     "Attempt to solve the equation for each variable and answer an Array of assignment statements (as strings, not parse trees) containing the solutions."
  2465.  
  2466.     | newTree stream body |
  2467.     ^theVariables asArray collect: 
  2468.         [: var |
  2469.          newTree _ theEquationTree transformBy: [: node | node].        "copy tree"
  2470.          newTree _ newTree restructureForAssigningTo: var.
  2471.          "build the assignment statement string in stream"
  2472.          stream _ (String new: 100) writeStream.
  2473.          stream nextPutAll: var asString.
  2474.          stream nextPutAll: ' _ '.
  2475.          body _ newTree arguments first printString.
  2476.          body _ body copyFrom: 2 to: body size - 1.    "strip off {} brackets"
  2477.          stream nextPutAll: body.
  2478.          stream contents]!
  2479.  
  2480. setEquationString: aString
  2481.     "Initialize myself from the given equation string. Parse the string and collect a list of the equation's variables."
  2482.  
  2483.     | parseTree |
  2484.     parseTree _ EquationParser parse: ('dummy ', aString) readStream.
  2485.     theEquationTree _ parseTree block statements first.
  2486.     theVariables _ theEquationTree allVariables asOrderedCollection.
  2487.  
  2488.     (parseTree block statements size > 2) ifTrue:
  2489.         [self error: 'Equations may not have multiple statements:
  2490.     ', parseTree block printString].
  2491.  
  2492.     ((theEquationTree isMemberOf: MessageNode) and:
  2493.       [theEquationTree selector key = #=]) ifFalse:
  2494.         [self error: 'This is not an equality equation:
  2495.     ', theEquationTree printString].! !
  2496. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2497.  
  2498. EquationTranslator class
  2499.     instanceVariableNames: ''!
  2500.  
  2501.  
  2502. !EquationTranslator class methodsFor: 'class initialization'!
  2503.  
  2504. initialize
  2505.     "This is a simple set of rules for manipulating equations. It has three inherent limitations. First, many of the functions that the Numbers class supports are not one-to-one. The inverse of such functions was chosen arbitrarily. Second, the inverse of some functions is not onto, thus functions like max: are not supported. Finally, rewriting boolean expressions will produce equations that this rewriting system cannot further rewrite."
  2506.     "EquationTranslator initialize"
  2507.  
  2508.     ReorderRules _ OrderedCollection new.
  2509.     RestructureRules _ OrderedCollection new.
  2510.  
  2511.     self initializeNormalArithmeticRules.
  2512.     self initializeSpecialArithmeticRules.    "these have non-unique inverses"
  2513.     self initializeUnaryFunctionRules.
  2514.     self initializeTrigFunctionRules.
  2515.     self initializeMathematicalFunctionRules.
  2516.     self initializeSpecialFunctionRules.
  2517.     self initializeCoercingRules.
  2518.  
  2519.     "The following rules can be removed if booleans are not needed:"
  2520.     self initializeTestingRules.            "these have non-unique inverses"
  2521.     self initializeComparingRules.        "these have non-unique inverses"
  2522.     self initializeBooleanFunctionRules.!
  2523.  
  2524. initializeBooleanFunctionRules
  2525.  
  2526.     | tr |
  2527.     tr _ TranslationRule.    "abbreviation"
  2528.     ReorderRules
  2529.         add: (tr from: 'a & b' to: 'b & a');
  2530.         add: (tr from: 'a | b' to: 'b | a');
  2531.         add: (tr from: 'a xor: b' to: 'b xor: a').
  2532.     RestructureRules
  2533.         add: (tr from: 'a not = b' to: 'a = b not');
  2534.         "add: (tr from: '(a & b) = c' to: 'a = c');"        "???"
  2535.         "add: (tr from: '(a | b) = c' to: 'a = c');"            "???"
  2536.         add: (tr from: '(a xor: b) = c' to: 'a = (b xor: c)').!
  2537.  
  2538. initializeCoercingRules
  2539.  
  2540.     | tr |
  2541.     tr _ TranslationRule.    "abbreviation"
  2542.     RestructureRules
  2543.         add: (tr from: 'a asFloat = b' to: 'a = b');
  2544.         add: (tr from: 'a asInteger = b' to: 'a = b');
  2545.         add: (tr from: 'a asFraction = b' to: 'a = b').!
  2546.  
  2547. initializeComparingRules
  2548.  
  2549.     | tr |
  2550.     tr _ TranslationRule.    "abbreviation"
  2551.     RestructureRules
  2552.         add: (tr from: '(a < b) = c' to: 'a = (c ifTrue: [b - 1] ifFalse: [b])');
  2553.         add: (tr from: '(a < b) = c' to: 'b = (c ifTrue: [a + 1] ifFalse: [a])');
  2554.         add: (tr from: '(a <= b) = c' to: 'a = (c ifTrue: [b] ifFalse: [b + 1])');
  2555.         add: (tr from: '(a <= b) = c' to: 'b = (c ifTrue: [a] ifFalse: [a - 1])');
  2556.         add: (tr from: '(a = b) = c' to: 'a = (c ifTrue: [b] ifFalse: [b + 1])');
  2557.         add: (tr from: '(a = b) = c' to: 'b = (c ifTrue: [a] ifFalse: [a + 1])');
  2558.         add: (tr from: '(a ~= b) = c' to: 'a = (c ifTrue: [b + 1] ifFalse: [b])');
  2559.         add: (tr from: '(a ~= b) = c' to: 'b = (c ifTrue: [a + 1] ifFalse: [a])');
  2560.         add: (tr from: '(a > b) = c' to: 'a = (c ifTrue: [b + 1] ifFalse: [b])');
  2561.         add: (tr from: '(a > b) = c' to: 'b = (c ifTrue: [a - 1] ifFalse: [a])');
  2562.         add: (tr from: '(a >= b) = c' to: 'a = (c ifTrue: [b] ifFalse: [b - 1])');
  2563.         add: (tr from: '(a >= b) = c' to: 'b = (c ifTrue: [a] ifFalse: [a + 1])').!
  2564.  
  2565. initializeMathematicalFunctionRules
  2566.  
  2567.     | tr |
  2568.     tr _ TranslationRule.    "abbreviation"
  2569.     RestructureRules
  2570.         add: (tr from: 'a exp = b' to: 'a = b ln');
  2571.         add: (tr from: 'a ln = b' to: 'a = b exp');
  2572.         add: (tr from: '(a log: b) = c' to: 'a = (b raisedTo: c)');
  2573.         add: (tr from: '(a log: b) = c' to: 'b = (a raisedTo: c reciprocal)');
  2574.         add: (tr from: '(a raisedTo: b) = c' to: 'a = (a raisedTo: b reciprocal)');
  2575.         add: (tr from: '(a raisedTo: b) = c' to: 'b = (c log: a)').!
  2576.  
  2577. initializeNormalArithmeticRules
  2578.  
  2579.     | tr |
  2580.     tr _ TranslationRule.    "abbreviation"
  2581.     ReorderRules
  2582.         add: (tr from: 'a = b' to: 'b = a');
  2583.         add: (tr from: 'a + b' to: 'b + a');
  2584.         add: (tr from: 'a - b' to: 'b negated + a');
  2585.         add: (tr from: 'a * b' to: 'b * a').
  2586.     RestructureRules
  2587.         add: (tr from: '(a + b) = c' to: 'a = (c - b)');
  2588.         add: (tr from: '(a - b) = c' to: 'a = (b + c)');
  2589.         add: (tr from: '(a * b) = c' to: 'a = (c / b)');
  2590.         add: (tr from: '(a / b) = c' to: 'a = (b * c)');
  2591.         add: (tr from: '(a / b) = c' to: 'b = (a / c)').!
  2592.  
  2593. initializeSpecialArithmeticRules
  2594.  
  2595.     | tr |
  2596.     tr _ TranslationRule.    "abbreviation"
  2597.     RestructureRules
  2598.         add: (tr from: '(a // b) = c' to: 'a = (b * c)');
  2599.         add: (tr from: '(a // b) = c' to: 'b = (a // c)');
  2600.         add: (tr from: '(a quo: b) = c' to: 'a = (b * c)');
  2601.         add: (tr from: '(a quo: b) = c' to: 'b = (a quo: c)');
  2602.         add: (tr from: '(a rem: b) = c' to: 'a = c');
  2603.         add: (tr from: '(a rem: b) = c' to: 'b = (a - c)');
  2604.         add: (tr from: '(a \\ b) = c' to: 'a = c');
  2605.         add: (tr from: '(a \\ b) = c' to: 'b = (a - c)');
  2606.         add: (tr from: '(a roundTo: b) = c' to: 'a = c');
  2607.         add: (tr from: '(a roundTo: b) = c' to: 'b = c');
  2608.         add: (tr from: '(a truncateTo: b) = c' to: 'a = c');
  2609.         add: (tr from: '(a truncateTo: b) = c' to: 'b = c').!
  2610.  
  2611. initializeSpecialFunctionRules
  2612.  
  2613.     | tr |
  2614.     tr _ TranslationRule.    "abbreviation"
  2615.     RestructureRules
  2616.         add: (tr from: '(a @ b) = c' to: 'a = c x');
  2617.         add: (tr from: '(a @ b) = c' to: 'b = c y');
  2618.         add: (tr from: 'a degreesToRadians = b' to: 'a = b radiansToDegrees');
  2619.         add: (tr from: 'a radiansToDegrees = b' to: 'a = b degreesToRadians');
  2620.         add: (tr from: 'a asPoint = b' to: 'a = b x').!
  2621.  
  2622. initializeTestingRules
  2623.  
  2624.     | tr |
  2625.     tr _ TranslationRule.    "abbreviation"
  2626.     RestructureRules
  2627.         add: (tr from: 'a even = b' to: 'a = (b ifTrue: [0] ifFalse: [1])');
  2628.         add: (tr from: 'a odd = b' to: 'a = (b ifTrue: [1] ifFalse: [0])');
  2629.         add: (tr from: 'a negative = b' to: 'a = (b ifTrue: [-1] ifFalse: [0])');
  2630.         add: (tr from: 'a positive = b' to: 'a = (b ifTrue: [1] ifFalse: [-1])');
  2631.         add: (tr from: 'a strictlyPositive = b' to: 'a = (b ifTrue: [1] ifFalse: [0])');
  2632.         add: (tr from: 'a sign = b' to:  'a = b').!
  2633.  
  2634. initializeTrigFunctionRules
  2635.  
  2636.     | tr |
  2637.     tr _ TranslationRule.    "abbreviation"
  2638.     RestructureRules
  2639.         add: (tr from: 'a arcCos = b' to: 'a = b cos');
  2640.         add: (tr from: 'a cos = b' to: 'a = b arcCos');
  2641.         add: (tr from: 'a arcSin = b' to: 'a = b sin');
  2642.         add: (tr from: 'a sin = b' to: 'a = b arcSin');
  2643.         add: (tr from: 'a arcTan = b' to: 'a = b tan');
  2644.         add: (tr from: 'a tan = b' to: 'a = b arcTan').!
  2645.  
  2646. initializeUnaryFunctionRules
  2647.  
  2648.     | tr |
  2649.     tr _ TranslationRule.    "abbreviation"
  2650.     RestructureRules
  2651.         add: (tr from: 'a abs = b abs' to: 'a = b abs');
  2652.         add: (tr from: 'a abs = b' to: 'a = b abs');
  2653.         add: (tr from: 'a negated = b negated' to: 'a = b');
  2654.         add: (tr from: 'a negated = b' to: 'a = b negated');
  2655.         add: (tr from: 'a reciprocal = b' to: 'a = b reciprocal');
  2656.         add: (tr from: 'a sqrt = b' to: 'a = b squared');
  2657.         add: (tr from: 'a squared = b' to: 'a = b sqrt');
  2658.         add: (tr from: 'a ceiling = b' to: 'a = b');
  2659.         add: (tr from: 'a floor = b' to: 'a = b');
  2660.         add: (tr from: 'a rounded = b' to: 'a = b');
  2661.         add: (tr from: 'a truncated = b' to: 'a = b').! !
  2662.  
  2663. !EquationTranslator class methodsFor: 'accessing'!
  2664.  
  2665. reorderRules
  2666.  
  2667.     ^ReorderRules!
  2668.  
  2669. restructureRules
  2670.  
  2671.     ^RestructureRules! !
  2672.  
  2673. !EquationTranslator class methodsFor: 'translating'!
  2674.  
  2675. methodsFor: equationString
  2676.     "Answer an array of assignment statement strings that represent the various inversions of the given equation. For example, the methods for 'a = (b + c)' are 'a _ b + c', 'b _ a - c', and 'c _ a - b'. The top level expression must be an '=' expression. Note that due to Smalltalk's left-to-right evaluation order, the top level expression of 'a = b + c' is the '+' expression, NOT the '=' expression; use parenthesis if necessary."
  2677.  
  2678.     ^(super new)
  2679.         setEquationString: equationString;
  2680.         computeMethods! !
  2681.  
  2682.  
  2683. StringHolder subclass: #ConstraintDefiner
  2684.     instanceVariableNames: 'client view '
  2685.     classVariableNames: ''
  2686.     poolDictionaries: ''
  2687.     category: 'ThingLabII-Things-Support'!
  2688.  
  2689.  
  2690. !ConstraintDefiner methodsFor: 'initialize-release'!
  2691.  
  2692. client: clientObject
  2693.     "Register a client object. This client will be updated with the prototype of the newly defined constraint when the user does 'accept'. My initial text is derived from the constraint currently held by the client. The client may be any object the understands the messages #baseConstraint, #baseConstraint:, #baseStrength, and #baseStrength:."
  2694.  
  2695.     client _ clientObject.
  2696.     contents _
  2697.         clientObject baseStrength, '\' withCRs,
  2698.         clientObject baseConstraint definitionString.!
  2699.  
  2700. view: aView
  2701.     "Set my view to the given view."
  2702.  
  2703.     view _ aView.! !
  2704.  
  2705. !ConstraintDefiner methodsFor: 'operation'!
  2706.  
  2707. buildConstraint: defString methods: methodStrings
  2708.  
  2709.     | parseTree strength varNames paths full root constraint |
  2710.     parseTree _  (EquationParser parse: ('dummy ', defString) readStream)
  2711.                 block statements first.
  2712.     "get strength (the receiver name)"
  2713.     strength _ parseTree receiver name asSymbol.
  2714.     "get constraint variable names (the message keywords, minus colons)"
  2715.     varNames _ parseTree selector key keywords
  2716.                     collect: [: n | (n copyFrom: 1 to: n size - 1) asSymbol].
  2717.     "get paths (the message arguments)"
  2718.     paths _ parseTree arguments collect:
  2719.         [: arg |
  2720.          full _ arg name asSymbol path.
  2721.          root _ full first.
  2722.          Reference on: root path: (full copyFrom: 2 to: full size)].
  2723.     constraint _ Constraint symbols: varNames methodStrings: methodStrings.
  2724.     constraint partlyBind: paths asArray.
  2725.     ^Array with: constraint with: strength!
  2726.  
  2727. contents: aString
  2728.  
  2729.     | pieces constraintDef methodDefs constraintAndStrength |
  2730.     pieces _ self splitIntoPieces: aString.
  2731.     (pieces size > 1)
  2732.         ifTrue:
  2733.             [constraintDef _ pieces first.
  2734.              methodDefs _ pieces copyFrom: 2 to: pieces size.
  2735.              constraintAndStrength _
  2736.                 self buildConstraint: constraintDef methods: methodDefs.
  2737.              client baseConstraint: (constraintAndStrength at: 1).
  2738.              client baseStrength: (constraintAndStrength at: 2)]
  2739.         ifFalse: [client baseConstraint: nil].
  2740.  
  2741.     (view notNil) ifTrue:
  2742.         [view model updateCaches.
  2743.          view displaySafe: [view displayView]].!
  2744.  
  2745. open
  2746.     "Open a view for this ConstraintDefiner. This call does not return."
  2747.  
  2748.     | constraintDefinerView topView |
  2749.     constraintDefinerView _ StringHolderView container: self.
  2750.     topView _ SpecialSystemView new.
  2751.     topView borderWidth: 1.
  2752.     topView model: constraintDefinerView model.
  2753.     topView addSubView: constraintDefinerView.
  2754.     topView label: 'Constraint Definer'.
  2755.     topView minimumSize: 100@50.
  2756.     topView icon: (Icon constantNamed: #default).
  2757.     topView controller open.!
  2758.  
  2759. splitIntoPieces: aString
  2760.     "Answer a collection of pieces for the given string. The pieces of the input string are separated by blank lines."
  2761.  
  2762.     | newLine pieces sourceStream pieceStream lastCharWasNewLine ch hasContent |
  2763.     newLine _ Character cr.
  2764.     pieces _ OrderedCollection new: 10.
  2765.     sourceStream _ aString readStream.
  2766.     [sourceStream atEnd] whileFalse:
  2767.         [pieceStream _ (String new: 100) writeStream.
  2768.          lastCharWasNewLine _ false.
  2769.          hasContent _ false.
  2770.          [(sourceStream atEnd not) and:
  2771.            [(lastCharWasNewLine & ((ch _ sourceStream next) = newLine)) not]]
  2772.             whileTrue:
  2773.                 [pieceStream nextPut: ch.
  2774.                  (ch isSeparator) ifFalse: [hasContent _ true].
  2775.                  lastCharWasNewLine _ (ch = newLine)].
  2776.          (hasContent) ifTrue: [pieces addLast: pieceStream contents]].
  2777.     ^pieces! !
  2778. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2779.  
  2780. ConstraintDefiner class
  2781.     instanceVariableNames: ''!
  2782.  
  2783.  
  2784. !ConstraintDefiner class methodsFor: 'instance creation'!
  2785.  
  2786. openOn: clientObject view: aView
  2787.     "Open a new ConstraintDefiner for the given client object. The client should understand the messages #baseConstraint, #baseConstraint:, #baseStrength, and #baseStrength:. The view, if non-nil, is updated after the constraint is changed."
  2788.  
  2789.     (self new)
  2790.         client: clientObject;
  2791.         view: aView;
  2792.         open! !
  2793.  
  2794. Object subclass: #ThingData
  2795.     instanceVariableNames: 'allConstraints determinedBy usedBy walkStrength stay mark '
  2796.     classVariableNames: ''
  2797.     poolDictionaries: ''
  2798.     category: 'ThingLabII-Things'!
  2799. ThingData comment:
  2800. 'I store the planner data that must be attached to each constrained part of a Thing. Currently this data is specific to the DeltaBlue algorithm, but it could be extended to support other planners.
  2801.  
  2802. Instance variables:
  2803.     walkStrength...    the Walkabout strength of my part <Strength>
  2804.     stayFlag...        true if my part will not change <Boolean>
  2805.     allConstraints...    all the constraints that reference my part {Constraint}
  2806.     determinedBy...    the constraint that currently determines
  2807.                     my part''s value or nil if there isn''t one <Constraint>
  2808.     usedBy...            constraints that currently use my part
  2809.                     as an input {Constraint}
  2810.     ancestors...        references to all the ThingDatas used to compute
  2811.                     my part {ThingData}
  2812. '!
  2813.  
  2814.  
  2815. !ThingData methodsFor: 'initialize-release'!
  2816.  
  2817. destroy
  2818.  
  2819.     allConstraints _ nil.
  2820.     determinedBy _ nil.
  2821.     usedBy _ nil.
  2822.     walkStrength _ nil.
  2823.     stay _ nil.
  2824.     mark _ nil.!
  2825.  
  2826. initialize
  2827.  
  2828.     allConstraints _ Array new.
  2829.     determinedBy _ nil.
  2830.     usedBy _ Array new.
  2831.     walkStrength _ Strength absoluteWeakest.
  2832.     stay _ true.
  2833.     mark _ 0.! !
  2834.  
  2835. !ThingData methodsFor: 'access'!
  2836.  
  2837. addConstraint: aConstraint
  2838.     "Add the given constraint to the set of constraints that refer to me."
  2839.  
  2840.     (allConstraints includes: aConstraint) ifFalse:
  2841.         [allConstraints _ allConstraints copyWith: aConstraint].!
  2842.  
  2843. addUsedBy: aConstraint
  2844.     "Add the given constraint to the set of constraints that use me as an input in the current dataflow."
  2845.  
  2846.     (usedBy includes: aConstraint) ifFalse:
  2847.         [usedBy _ usedBy copyWith: aConstraint].!
  2848.  
  2849. constraints
  2850.     "Answer the set of constraints that refer to me."
  2851.  
  2852.     ^allConstraints!
  2853.  
  2854. determinedBy
  2855.     "Answer the constraint that determines me in the current dataflow."
  2856.  
  2857.     ^determinedBy!
  2858.  
  2859. determinedBy: aConstraint
  2860.     "Set the given constraint to be the one that determines me in the current data flow."
  2861.  
  2862.     determinedBy _ aConstraint.!
  2863.  
  2864. mark
  2865.     "Answer my mark value."
  2866.  
  2867.     ^mark!
  2868.  
  2869. mark: markValue
  2870.     "Set my mark value."
  2871.  
  2872.     mark _ markValue.!
  2873.  
  2874. removeConstraint: aConstraint
  2875.     "Remove the given constraint from the set of constraints that refer to me."
  2876.  
  2877.     allConstraints _ allConstraints copyWithout: aConstraint.!
  2878.  
  2879. removeUsedBy: aConstraint
  2880.     "Remove the given constraint from the set of constraints that use me as an input in the current dataflow."
  2881.  
  2882.     usedBy _ usedBy copyWithout: aConstraint.!
  2883.  
  2884. stay
  2885.     "Answer my stay value."
  2886.  
  2887.     ^stay!
  2888.  
  2889. stay: aBoolean
  2890.     "Set my stay value."
  2891.  
  2892.     stay _ aBoolean.!
  2893.  
  2894. usedBy
  2895.     "Answer the set of constraints that use me as an input in the current dataflow."
  2896.  
  2897.     ^usedBy!
  2898.  
  2899. walkStrength
  2900.     "Answer my walkabout strength in the current dataflow."
  2901.  
  2902.     ^walkStrength!
  2903.  
  2904. walkStrength: aStrength
  2905.     "Set my walkabout strength in the current dataflow."
  2906.  
  2907.     walkStrength _ aStrength.!
  2908.  
  2909. ws
  2910.     "Shorthand for 'walkStrength' to make module 'isPossiblexxx' methods more readable."
  2911.  
  2912.     ^walkStrength! !
  2913.  
  2914. !ThingData methodsFor: 'module compiler'!
  2915.  
  2916. ancestors
  2917.     "Answer the ThingDatas of all variables on which my variable depends (i.e. all upstream variables), including myself."
  2918.  
  2919.     | processed ancestors todo c |
  2920.     processed _ IdentitySet new: 20.    "processed constraints"
  2921.     ancestors _ OrderedCollection new: 100.
  2922.     ancestors add: self.
  2923.     todo _ OrderedCollection new: 100.
  2924.     todo add: self.
  2925.     [todo isEmpty] whileFalse:
  2926.         [c _ todo removeFirst determinedBy.
  2927.          (c notNil and: [(processed includes: c) not]) ifTrue:
  2928.             [processed add: c.
  2929.              c whichMethod inDatasIn: c thingDatas do:
  2930.                 [: in |
  2931.                  todo add: in.
  2932.                  ancestors add: in]]].
  2933.     ^ancestors!
  2934.  
  2935. initExternal: varEntry
  2936.  
  2937.     determinedBy _ nil.
  2938.     usedBy _ Array new.
  2939.     walkStrength _ WalkEquation external: varEntry.
  2940.     self stay: false.!
  2941.  
  2942. initInternal
  2943.  
  2944.     determinedBy _ nil.
  2945.     usedBy _ Array new.
  2946.     walkStrength _ Strength absoluteWeakest.
  2947.     self stay: true.! !
  2948.  
  2949. !ThingData methodsFor: 'printing'!
  2950.  
  2951. longPrintOn: aStream
  2952.  
  2953.     self shortPrintOn: aStream.
  2954.     aStream nextPutAll: 'Referenced by: '.
  2955.     (allConstraints isEmpty)
  2956.         ifTrue: [aStream nextPutAll: 'nobody']
  2957.         ifFalse:
  2958.             [allConstraints do:
  2959.                 [: c | aStream cr; tab. c shortPrintOn: aStream]].
  2960.     aStream cr; nextPutAll: 'Determined by: '.
  2961.     (determinedBy isNil)
  2962.         ifTrue: [aStream nextPutAll: 'nobody']
  2963.         ifFalse: [aStream cr; tab. determinedBy shortPrintOn: aStream].
  2964.     aStream cr; nextPutAll: 'Used by: '.
  2965.     (usedBy isEmpty)
  2966.         ifTrue: [aStream nextPutAll: 'nobody']
  2967.         ifFalse:
  2968.             [usedBy do:
  2969.                 [: c | aStream cr; tab. c shortPrintOn: aStream]].
  2970.     aStream cr.!
  2971.  
  2972. printOn: aStream
  2973.  
  2974.     (Sensor leftShiftDown)
  2975.         ifTrue: [self longPrintOn: aStream]
  2976.         ifFalse: [self shortPrintOn: aStream].!
  2977.  
  2978. shortPrintOn: aStream
  2979.  
  2980.     aStream nextPutAll: 'TD(', self asOop printString, ', '.
  2981.     aStream nextPutAll: walkStrength printString, ', '.
  2982.     aStream nextPutAll: (self stay ifTrue: ['stay'] ifFalse: ['not stay']).
  2983.     aStream nextPutAll: ')'.
  2984.     aStream cr.! !
  2985. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2986.  
  2987. ThingData class
  2988.     instanceVariableNames: ''!
  2989.  
  2990.  
  2991. !ThingData class methodsFor: 'instance creation'!
  2992.  
  2993. new
  2994.  
  2995.     ^super new initialize! !
  2996.  
  2997. View subclass: #SceneView
  2998.     instanceVariableNames: 'scrollOffset enclosingRect backgroundForm scratchForm visibleForeground selectedForeground '
  2999.     classVariableNames: ''
  3000.     poolDictionaries: ''
  3001.     category: 'ThingLabII-UI-Framework'!
  3002. SceneView comment:
  3003. 'This class is used to display a Scene. The picture may be scrolled by adjusting ''scrollOffset''. The default controller for SceneView is SceneController.
  3004.  
  3005. SceneViews encapsulate the notion of a changing foreground and a fixed background during interactive updates. During an interaction (such as dragging), some glyphs may not change location or appearance. These are part of the "background". All remaining glyphs ("foreground" glyphs) are painted against this unchanging backdrop during the interaction.
  3006.  
  3007. Instance Variables:
  3008.     scrollOffset            the current scroll offset of this view
  3009.     enclosingRect         a rectangle large enough to contain all the objects in the scene, plus a small border (this is a cache that must be recomputed when glyphs are moved, added, or removed from the scene)
  3010.  
  3011. The following instance variables are only meaningful after ''computeBackground'' has been sent:
  3012.     backgroundForm        a <Form> containing the fixed background
  3013.     visibleForeground        glyphs that are changing but not selected during an interaction
  3014.     selectedForeground    selected glyphs that are changing during an interaction'!
  3015.  
  3016.  
  3017. !SceneView methodsFor: 'initialize-release'!
  3018.  
  3019. initialize
  3020.  
  3021.     super initialize.
  3022.     scrollOffset _ 0@0.
  3023.     enclosingRect _ nil.! !
  3024.  
  3025. !SceneView methodsFor: 'label access'!
  3026.  
  3027. newLabel: aString
  3028.     "Change my label to be the given string."
  3029.  
  3030.     self topView deEmphasize.
  3031.     self topView newLabel: aString.
  3032.     self topView emphasize.! !
  3033.  
  3034. !SceneView methodsFor: 'displaying'!
  3035.  
  3036. computeBackground
  3037.     "Compute the backgroundForm and the two lists, visibleForeground and selectedForeground. These are used by the 'displayFeedback' and 'displayFeedbackWithBox:width:' operations."
  3038.  
  3039.     | viewExtent viewOrigin clipBox |
  3040.     viewExtent _ self enclosingRectangle rounded extent max: self insetDisplayBox extent.
  3041.     backgroundForm _ Form extent: viewExtent.
  3042.     scratchForm _ Form extent: viewExtent.
  3043.     viewOrigin _ self viewOrigin.
  3044.     clipBox _ backgroundForm computeBoundingBox.
  3045.     self displayBorderOn: backgroundForm at: viewOrigin clippingBox: clipBox.
  3046.  
  3047.     visibleForeground _ OrderedCollection new: 100.
  3048.     model visibleGlyphs do:
  3049.         [: g |
  3050.          (model isChanging: g)
  3051.             ifTrue: [visibleForeground add: g]
  3052.             ifFalse: [g displayOn: backgroundForm at: viewOrigin clippingBox: clipBox]].
  3053.  
  3054.     selectedForeground _ OrderedCollection new: 100.
  3055.     model selected do:
  3056.         [: g |
  3057.          (model isChanging: g)
  3058.             ifTrue: [selectedForeground add: g]
  3059.             ifFalse: [g highlightOn: backgroundForm at: viewOrigin clippingBox: clipBox]].!
  3060.  
  3061. displayBorderOn: aDisplayMedium at: aPoint clippingBox: clipBox
  3062.     "Draw a boundary line that encloses all glyphs in the scene."
  3063.  
  3064.     | borderBox |
  3065.     borderBox _ (aPoint + enclosingRect origin) extent:
  3066.                     (enclosingRect extent max: clipBox extent).
  3067.     borderBox _ borderBox insetOriginBy: 4@4 cornerBy: 4@4.
  3068.     aDisplayMedium
  3069.         border: borderBox
  3070.         widthRectangle: (1@1 corner: 1@1)
  3071.         mask: (Form gray)
  3072.         clippingBox: clipBox.
  3073.  
  3074.     "display cross hairs at origin"
  3075.     aDisplayMedium black: (aPoint + (2@4) extent: 5@1).
  3076.     aDisplayMedium black: (aPoint + (4@2) extent: 1@5).!
  3077.  
  3078. displayFeedback
  3079.     "Update my display during a user interaction. The client must have called 'computeBackgroundWhileChanging:' to prepare for this operation."
  3080.  
  3081.     self displayFeedbackWithBox: nil width: nil.!
  3082.  
  3083. displayFeedbackWithBox: aRectangle width: w
  3084.     "Update my display during a user interaction. The client must have called 'computeBackgroundWhileChanging:' to prepare for this operation. If it is not nil, the given rectangle (in model coordinates) is drawn with the given border width as additional feedback."
  3085.  
  3086.     | viewOrigin clipBox |
  3087.     viewOrigin _ self viewOrigin.
  3088.     clipBox _ backgroundForm computeBoundingBox.
  3089.     backgroundForm displayOn: scratchForm at: 0@0.
  3090.     visibleForeground do:
  3091.         [: g | g displayOn: scratchForm at: viewOrigin clippingBox: clipBox].
  3092.     selectedForeground do:
  3093.         [: g | g highlightOn: scratchForm at: viewOrigin clippingBox: clipBox].
  3094.     (aRectangle notNil) ifTrue:
  3095.         [scratchForm
  3096.             border: (aRectangle translateBy: viewOrigin)
  3097.             widthRectangle: (w@w corner: w@w)
  3098.             mask: (Form black)
  3099.             clippingBox: clipBox].
  3100.     scratchForm
  3101.         displayOn: Display
  3102.         at: self insetDisplayBox origin + scrollOffset
  3103.         clippingBox: self insetDisplayBox.!
  3104.  
  3105. displayScene
  3106.     "Display the scene."
  3107.  
  3108.     self computeBackground.
  3109.     self displayFeedback.!
  3110.  
  3111. displayView
  3112.     "This method is called by the system when the top view is framed or moved."
  3113.  
  3114.     "adjust offset in case the view has been resized"
  3115.     self scrollOffset: scrollOffset.
  3116.     self displayScene.! !
  3117.  
  3118. !SceneView methodsFor: 'controller access'!
  3119.  
  3120. defaultControllerClass
  3121.  
  3122.     ^SceneController! !
  3123.  
  3124. !SceneView methodsFor: 'scrolling'!
  3125.  
  3126. scrollOffset
  3127.     "Answer my scrolling offset."
  3128.  
  3129.     ^scrollOffset!
  3130.  
  3131. scrollOffset: aPoint
  3132.     "Set my scroll offset after first limiting it to lie within the envelope of permissible values."
  3133.  
  3134.     | limits |
  3135.     limits _ self scrollOffsetLimits.
  3136.     scrollOffset _ (aPoint max: limits origin) min: limits corner.!
  3137.  
  3138. scrollOffsetLimits
  3139.     "Answer the envelope of possible offset values (a possibly empty rectangle in the upper-left quadrant of the Cartesian plane)."
  3140.  
  3141.     | extent |
  3142.     extent _ (self enclosingRectangle extent - self insetDisplayBox extent) max: 0@0.
  3143.     ^(0@0 - extent) corner: 0@0! !
  3144.  
  3145. !SceneView methodsFor: 'coordinates'!
  3146.  
  3147. computeEnclosingRectangle
  3148.     "Compute a rectangle capable of enclosing all glyphs in this view. The rectangle's corners are computed and then expanded to allow room for a border. This method should be called any time glyphs are added, removed or moved."
  3149.  
  3150.     | min max g b |
  3151.     min _ 6@6.
  3152.     max _ 6@6.
  3153.     model allGlyphs do:
  3154.         [: g |
  3155.          b _ g boundingBox.
  3156.          min _ min min: b origin.
  3157.          max _ max max: b corner].
  3158.     enclosingRect _ (min - (6@6)) corner: (max + (6@6)).!
  3159.  
  3160. displayToModelPoint: aDisplayPoint
  3161.     "Converts the given point in Display coordinates to the corresponding point in model coordinates."
  3162.  
  3163.     ^enclosingRect origin + (aDisplayPoint - self insetDisplayBox origin) - scrollOffset!
  3164.  
  3165. enclosingRectangle
  3166.     "Answer a rectangle capable of enclosing all glyphs in this view. This rectangle is expensive to compute, so it is cached in 'enclosingRect'."
  3167.  
  3168.     (enclosingRect isNil) ifTrue: [self computeEnclosingRectangle].
  3169.     ^enclosingRect!
  3170.  
  3171. modelToDisplayPoint: aModelPoint
  3172.     "Converts the given point in model coordinates to the corresponding point in Display coordinates (the inverse of 'displayToModelPoint:')."
  3173.  
  3174.     ^self insetDisplayBox origin + (aModelPoint - enclosingRect origin) + scrollOffset!
  3175.  
  3176. viewOrigin
  3177.     "Answer the origin of the view's coordinate system relative to 0@0."
  3178.  
  3179.     ^(0@0) - enclosingRect origin! !
  3180. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3181.  
  3182. SceneView class
  3183.     instanceVariableNames: ''!
  3184.  
  3185.  
  3186. !SceneView class methodsFor: 'instance creation'!
  3187.  
  3188. on: aScene
  3189.     "Create a new view on the given Scene."
  3190.  
  3191.     ^self new model: aScene!
  3192.  
  3193. openOn: aScene
  3194.     "Open a new view on the given Scene."
  3195.  
  3196.     self
  3197.         openWithSubview: (self on: aScene)
  3198.         label: 'Scene'.!
  3199.  
  3200. openWithSubview: aView label: labelString
  3201.     "Open a StandardSystemView with the given label and the given view as a subview."
  3202.  
  3203.     | topView |
  3204.     topView _ SpecialSystemView
  3205.         model: nil
  3206.         label: labelString
  3207.         minimumSize: 60@60.
  3208.     topView
  3209.         borderWidth: 1;
  3210.         addSubView: aView.
  3211.     topView controller open.!
  3212.  
  3213. openWithSubview: aView label: labelString fromHolder: aPartHolder zoomFrom: fromRect to: toRect
  3214.     "Open a SpecialSystemView with the given label and the given view as a subview zooming open from the given rectangle."
  3215.  
  3216.     | topView controller |
  3217.     controller _ SpecialSystemController new.
  3218.     controller
  3219.         fromHolder: aPartHolder;
  3220.         fromFrame: fromRect.
  3221.     topView _ SpecialSystemView
  3222.         model: nil
  3223.         label: labelString
  3224.         minimumSize: 60@60.
  3225.     topView
  3226.         borderWidth: 1;
  3227.         controller: controller;
  3228.         addSubView: aView.
  3229.     ((fromRect notNil) & (toRect notNil))
  3230.         ifTrue:
  3231.             [Display zoom: fromRect to: toRect duration: 260.
  3232.              topView window: (0@0 extent: toRect extent) viewport: toRect.
  3233.              topView controller openDisplayAt: toRect center]
  3234.         ifFalse: [topView controller open].! !
  3235.  
  3236. Parser subclass: #EquationParser
  3237.     instanceVariableNames: ''
  3238.     classVariableNames: ''
  3239.     poolDictionaries: ''
  3240.     category: 'ThingLabII-Equations'!
  3241.  
  3242.  
  3243. !EquationParser methodsFor: 'public access'!
  3244.  
  3245. editor
  3246.     "I am never called from an interactive editor."
  3247.  
  3248.     ^nil!
  3249.  
  3250. encoder
  3251.     "Answer my encoder."
  3252.  
  3253.     ^encoder!
  3254.  
  3255. parse: sourceStream
  3256.     "Parse the given source stream and answer the resulting parse tree. The source stream contents must represent a syntactically correct Smalltalk method definition such as:
  3257.     foo
  3258.         a _ b.
  3259.         c _ 55 * a + b.
  3260. That is, there must be a method header followed by a series of statements."
  3261.  
  3262.     | meth |
  3263.     failBlock _ [].
  3264.     self init: sourceStream notifying: nil failBlock: failBlock.
  3265.     encoder _ EquationEncoder new init: Object context: nil notifying: self.
  3266.     meth _ self method: false context: nil.
  3267.     "break cycles & mitigate refct overflow"
  3268.     failBlock _ parseNode _ nil.
  3269.     encoder release.
  3270.     ^meth!
  3271.  
  3272. parse: sourceStream in: aClass
  3273.     "Parse the given source stream for the given class and answer the resulting parse tree. The source stream contents must represent a syntactically correct Smalltalk method definition such as:
  3274.     foo
  3275.         a _ b.
  3276.         c _ 55 * a + b.
  3277. That is, there must be a method header followed by a series of statements."
  3278.  
  3279.     | meth |
  3280.     failBlock _ [self error: 'Module Compiler Error'].
  3281.     self init: sourceStream notifying: nil failBlock: failBlock.
  3282.     encoder _ EquationEncoder new init: aClass context: nil notifying: self.
  3283.     meth _ self method: false context: nil.
  3284.     "break cycles & mitigate refct overflow"
  3285.     failBlock _ parseNode _ nil.
  3286.     encoder release.
  3287.     ^meth!
  3288.  
  3289. parse: sourceStream withEncoder: anEncoder
  3290.     "Parse the given source stream using the given encoder and answer the resulting parse tree. The source stream contents must represent a syntactically correct Smalltalk method definition such as:
  3291.     foo
  3292.         a _ b.
  3293.         c _ 55 * a + b.
  3294. That is, there must be a method header followed by a series of statements."
  3295.  
  3296.     | meth |
  3297.     failBlock _ [self error: 'Module Compiler Error'].
  3298.     self init: sourceStream notifying: nil failBlock: failBlock.
  3299.     encoder _ anEncoder.
  3300.     meth _ self method: false context: nil.
  3301.     "break cycles & mitigate refct overflow"
  3302.     failBlock _ parseNode _ nil.
  3303.     ^meth! !
  3304. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3305.  
  3306. EquationParser class
  3307.     instanceVariableNames: ''!
  3308.  
  3309.  
  3310. !EquationParser class methodsFor: 'parsing'!
  3311.  
  3312. parse: aStream
  3313.     "Parse the given source stream and answer the resulting parse tree."
  3314.  
  3315.     ^(super new) parse: aStream!
  3316.  
  3317. parse: aStream in: aClass
  3318.     "Parse the given source stream for the given class and answer the resulting parse tree."
  3319.  
  3320.     ^(super new) parse: aStream in: aClass!
  3321.  
  3322. parse: aStream withEncoder: anEncoder
  3323.     "Parse the given stream using the supplied encoder and answer the resulting parse tree."
  3324.  
  3325.     ^(super new) parse: aStream withEncoder: anEncoder! !
  3326.  
  3327. CharacterScanner subclass: #QuickPrint
  3328.     instanceVariableNames: ''
  3329.     classVariableNames: ''
  3330.     poolDictionaries: ''
  3331.     category: 'ThingLabII-UI-Support'!
  3332. QuickPrint comment:
  3333. 'This class supports fast character string display. It is significantly faster than using a Paragraph for the same purpose.'!
  3334.  
  3335.  
  3336. !QuickPrint methodsFor: 'displaying'!
  3337.  
  3338. drawString: aString
  3339.     "Draw the given string."
  3340.  
  3341.     destX _ clipX.
  3342.     destY _ clipY.
  3343.     self
  3344.         scanCharactersFrom: 1
  3345.         to: (aString size)
  3346.         in: aString
  3347.         rightX: (clipX + clipWidth)
  3348.         stopConditions: stopConditions
  3349.         displaying: true!
  3350.  
  3351. stringWidth: aString
  3352.     "Answer the width of the given string."
  3353.  
  3354.     destX _ 0.
  3355.     destY _ 0.
  3356.     self
  3357.         scanCharactersFrom: 1
  3358.         to: (aString size)
  3359.         in: aString
  3360.         rightX: 10000    "virtual infinity"
  3361.         stopConditions: stopConditions
  3362.         displaying: false.
  3363.     ^destX! !
  3364.  
  3365. !QuickPrint methodsFor: 'positioning'!
  3366.  
  3367. downBy: offset
  3368.     "Move the top border of my clipping box down by the given amount."
  3369.  
  3370.     | clipBox |
  3371.     clipBox _ self clipRect.
  3372.     clipBox top: ((clipBox top + offset) min: clipBox bottom).
  3373.     self clipRect: clipBox.!
  3374.  
  3375. rightBy: offset
  3376.     "Move the left border of my clipping box right by the given amount."
  3377.  
  3378.     | clipBox |
  3379.     clipBox _ self clipRect.
  3380.     clipBox left: ((clipBox left + offset) min: clipBox right).
  3381.     self clipRect: clipBox.! !
  3382.  
  3383. !QuickPrint methodsFor: 'private'!
  3384.  
  3385. newOn: aForm box: aRectangle
  3386.     "Initialize myself."
  3387.  
  3388.     textStyle _ TextStyle default.
  3389.     font _ textStyle fontAt: 1.
  3390.     destForm _ aForm.
  3391.     halftoneForm _ Form black.
  3392.     combinationRule _ Form over.
  3393.     self clipRect: aRectangle.
  3394.     sourceY _ 0.
  3395.     "sourceX is set when selecting the character from the font strike bitmap"
  3396.     self setStopConditions.!
  3397.  
  3398. setStopConditions
  3399.     "Set default stop conditions for the font."
  3400.  
  3401.     spaceWidth _ font spaceWidth. 
  3402.     sourceForm _ font glyphs.
  3403.     xTable _ font xTable.
  3404.     height _ font height.
  3405.     stopConditions _ font stopConditions.
  3406.     stopConditions at: CR asInteger + 1 put: #cr.
  3407.     stopConditions at: 10 + 1 put: #cr.
  3408.     stopConditions at: EndOfRun put: #endOfRun.
  3409.     stopConditions at: CrossedX put: #crossedX.
  3410.     stopConditions at: Ctrls asInteger + 1 put: #onePixelSpace.
  3411.     stopConditions at: CtrlS asInteger + 1 put: #onePixelBackspace.
  3412.     stopConditions at: Ctrlz asInteger + 1 put: #characterNotInFont.! !
  3413. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3414.  
  3415. QuickPrint class
  3416.     instanceVariableNames: ''!
  3417.  
  3418.  
  3419. !QuickPrint class methodsFor: 'instance creation'!
  3420.  
  3421. newOn: aForm box: aRectangle
  3422.     "Create an instance to print on the given form in the given rectangle."
  3423.  
  3424.     ^(super new) newOn: aForm box: aRectangle! !
  3425.  
  3426. !QuickPrint class methodsFor: 'queries'!
  3427.  
  3428. lineHeight
  3429.     "Answer the height of the font used by QuickPrint."
  3430.  
  3431.     ^(TextStyle default fontAt: 1) height!
  3432.  
  3433. width: aString
  3434.     "Answer the width of the printed representation of the given string in pixels."
  3435.  
  3436.     | scanner |
  3437.     scanner _ QuickPrint
  3438.         newOn: Display
  3439.         box: (0@0 corner: 0@0).
  3440.     ^scanner stringWidth: aString! !
  3441.  
  3442. !QuickPrint class methodsFor: 'example'!
  3443.  
  3444. example
  3445.     "This will quickly print all the numbers from 1 to 100 on the display and then answer the width and height of the string 'hello world'."
  3446.     "QuickPrint example"
  3447.  
  3448.     | scanner |
  3449.     scanner _ QuickPrint
  3450.         newOn: Display
  3451.         box: (20@70 corner: 80@90).
  3452.     1 to: 100 do: [: i | scanner drawString: i printString].
  3453.     ^(QuickPrint width: 'hello world')@(QuickPrint lineHeight)! !
  3454.  
  3455. Object subclass: #ShortestPaths
  3456.     instanceVariableNames: 'vertexCount vertexTable transitionList distances toDo '
  3457.     classVariableNames: ''
  3458.     poolDictionaries: ''
  3459.     category: 'ThingLabII-UI-Layout'!
  3460.  
  3461.  
  3462. !ShortestPaths methodsFor: 'all'!
  3463.  
  3464. computeDistances: aMatrix
  3465.     "Initialize the distance matrix and various constants."
  3466.     "Note: If using Floyd's algorithm, aMatrix should be copied since 'distances' is modified by the algorithm."
  3467.  
  3468.     distances _ aMatrix.
  3469.     ^self dijkstra!
  3470.  
  3471. dijkstra
  3472.     "Compute the least-cost array by using Dijkstra's algorithm to compute the least cost paths from each vertex in turn."
  3473.  
  3474.     | costs v |
  3475.     self dijkstraSetup.
  3476.     costs _ Array new: vertexCount.
  3477.     v _ 1.
  3478.     [v <= vertexCount] whileTrue:
  3479.         [costs at: v put: (self dijkstraComputeRow: v).
  3480.          v _ v + 1].
  3481.     ^Matrix new setRows: costs!
  3482.  
  3483. dijkstraComputeRow: vertex
  3484.     "Compute one row of the cost matrix using Dijkstra's algorithm."
  3485.  
  3486.     | costRow element v vCost transitions count i nextV |
  3487.     self dijkstraRowSetupFor: vertex.
  3488.     costRow _ Array new: vertexCount.
  3489.     [toDo size == 0] whileFalse:
  3490.         [element _ toDo removeMin.
  3491.          v _ element label.
  3492.          vCost _ element cost.
  3493.          costRow at: v put: vCost.
  3494.          vCost _ vCost + 1.
  3495.          transitions _ transitionList at: v.
  3496.          count _ transitions size.
  3497.          i _ 1.
  3498.          [i <= count] whileTrue:
  3499.             [nextV _ vertexTable at: (transitions at: i).
  3500.              (vCost < nextV cost) ifTrue:
  3501.                 [nextV cost: vCost.
  3502.                  toDo relocate: nextV].
  3503.              i _ i + 1]].
  3504.     costRow at: vertex put: 0.
  3505.     ^costRow!
  3506.  
  3507. dijkstraRowSetupFor: vertex
  3508.     "Initialize the set of unvisited vertices ('toDo') for finding the shortest paths to all other vertices from the given vertex."
  3509.  
  3510.     | transitions count i v |
  3511.     (vertexTable at: vertex) cost: 0.
  3512.     toDo initializeWithVertices: vertexTable except: vertex cost: 100000.
  3513.     transitions _ transitionList at: vertex.
  3514.     count _ transitions size.
  3515.     i _ 1.
  3516.     [i <= count] whileTrue:
  3517.         [v _ vertexTable at: (transitions at: i).
  3518.          v cost: 1.
  3519.          toDo relocate: v.
  3520.          i _ i + 1].!
  3521.  
  3522. dijkstraSetup
  3523.     "Initialize the transitionsList and vertexTable for Dijkstra's algorithm."
  3524.  
  3525.     | i dists edges j |
  3526.     vertexCount _ distances rowCount.
  3527.     transitionList _ Array new: vertexCount.
  3528.     vertexTable _ Array new: vertexCount.
  3529.     i _ 1.
  3530.     [i <= vertexCount] whileTrue:
  3531.         [dists _ distances row: i.
  3532.          edges _ OrderedCollection new: vertexCount.
  3533.          j _ 1.
  3534.          [j <= vertexCount] whileTrue:
  3535.             [((dists at: j) == 1) ifTrue: [edges add: j].
  3536.              j _ j + 1].
  3537.          transitionList at: i put: edges asArray.
  3538.          vertexTable at: i put: (LayoutGlyph label: i).
  3539.          i _ i + 1].
  3540.     toDo _ PriorityQueue new: vertexCount.!
  3541.  
  3542. floyd
  3543.     "Compute the transitive closure of the distance function using Floyd's algorithm."
  3544.  
  3545.     | matrixSize row newDist k i j |
  3546.     matrixSize _ distances rowCount.
  3547.     k _ 0.
  3548.     [k < matrixSize] whileTrue:
  3549.         [k _ k + 1.
  3550.          i _ 0.
  3551.          [i < matrixSize] whileTrue:
  3552.             [i _ i + 1.
  3553.              row _ distances row: i.
  3554.              j _ 0.
  3555.              [j < matrixSize] whileTrue:
  3556.                 [j _ j + 1.
  3557.                  "distances from i to j via k"
  3558.                  newDist _ (row at: k) + (distances row: k col: j).
  3559.                  (newDist < (row at: j)) ifTrue:
  3560.                     [row at: j put: newDist]]]].
  3561.     ^distances! !
  3562. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3563.  
  3564. ShortestPaths class
  3565.     instanceVariableNames: ''!
  3566.  
  3567.  
  3568. !ShortestPaths class methodsFor: 'computing'!
  3569.  
  3570. computeDistances: initialDistanceMatrix
  3571.     "Given an initial distance matrix, answer the shortest path cost matrix for the graph. The distance matrix has d(i,j) = 1 if there is a direct path from i to j in the graph, d(i,j) > 1 if there is no direct path from i to j in the graph, and d(i,i) = 0 for all i."
  3572.  
  3573.     ^self new computeDistances: initialDistanceMatrix! !
  3574.  
  3575. !ShortestPaths class methodsFor: 'examples'!
  3576.  
  3577. example1
  3578.     "Answers the shortest path matrix for a 3 vertex chain."
  3579.     "ShortestPaths example1"
  3580.  
  3581.     ^ShortestPaths computeDistances:
  3582.         ((Matrix rows: 3 columns: 3)
  3583.             fill: 1000;
  3584.             row: 1 col: 1 put: 0;
  3585.             row: 2 col: 2 put: 0;
  3586.             row: 3 col: 3 put: 0;
  3587.             row: 1 col: 2 put: 1;
  3588.             row: 2 col: 1 put: 1;
  3589.             row: 2 col: 3 put: 1;
  3590.             row: 3 col: 2 put: 1)!
  3591.  
  3592. example2: vertexCount
  3593.     "Answers the time required to compute the shortest paths matrix for an N vertex ring."
  3594.     "ShortestPaths example2: 80"
  3595.     "Here are some figures for various values of N using different algorithms:
  3596.  
  3597.         N = 5, 10, 20, 40, 80, 160
  3598.         20 92 400 1660 7329 32226 -- dijkstra, final implementation
  3599.         31 143 512 2122 9236 40642 -- dijkstra, backrefs
  3600.         31 103 482 2070 9809 50399 -- dijkstra, better locate
  3601.         71 133 636 2777 13284  66410 -- dijkstra, original
  3602.         21 82 594 4520 35936 275817 -- floyd
  3603.         20 134 1014 7472 58271 <missing> -- old floyd
  3604.         41 430 3065 23114 183219 <missing> -- john
  3605.     These figures were collected on a Mac SE with an Irwin 25 MHz accellerator. They provide a glimpse into the complex process of optimizing an algorithm and how effective such optimization can be. 'john' was my original naive solution to problem. Floyd is an implementation of Floyd's algorithm and Dijkstra is an implementation of Dijkstra's algorithm.
  3606.     Finally, a few tests on the extreme's of Dijkstra's algorithm:
  3607.         N = 5, 10, 20, 40, 80, 160
  3608.         21  82 174 676 2788 10895 -- graph with no edges
  3609.         21 123 584 3536 24272 175285 -- fully connected graph"
  3610.  
  3611.     | m |
  3612.     m _ Matrix rows: vertexCount columns: vertexCount.
  3613.     m fill: 1000.
  3614.     1 to: vertexCount do: [: i | m row: i col: i put: 0].
  3615.     1 to: vertexCount-1 do:
  3616.         [: i |
  3617.          m row: i col: i+1 put: 1.
  3618.          m row: i+1 col: i put: 1].
  3619.     m row: 1 col: vertexCount put: 1.
  3620.     m row: vertexCount col: 1 put: 1.
  3621.     ^Time millisecondsToRun: [ShortestPaths computeDistances: m]! !
  3622.  
  3623. Object subclass: #BluePlanner
  3624.     instanceVariableNames: 'thingDatas sortedConstraints '
  3625.     classVariableNames: ''
  3626.     poolDictionaries: ''
  3627.     category: 'ThingLabII'!
  3628. BluePlanner comment:
  3629. 'I embody a simple, non-incremental constraint planning algorithm known as Blue.'!
  3630.  
  3631.  
  3632. !BluePlanner methodsFor: 'initialize-release'!
  3633.  
  3634. on: aThing
  3635.     "Initialize myself for satisfying the constraints on the given Thing."
  3636.     "Note: constraint satisfaction could be done faster if we used one BluePlanner for each constraint partition. The partitions could be maintained incrementally. Food for thought..."
  3637.  
  3638.     | allConstraints |
  3639.     thingDatas _ IdentitySet new: 40.
  3640.     aThing allThingsDo:
  3641.         [: thing | thingDatas addAll: thing thingDatas].
  3642.     allConstraints _ IdentitySet new: 40.
  3643.     thingDatas do:
  3644.         [: thingData | allConstraints addAll: thingData constraints].
  3645.     sortedConstraints _
  3646.         (SortedCollection new: 200)
  3647.             sortBlock: [: i : j | i isStrongerThan: j].
  3648.     sortedConstraints addAll: allConstraints.! !
  3649.  
  3650. !BluePlanner methodsFor: 'planning'!
  3651.  
  3652. plan
  3653.     "Figure out how to satisfy the constraints and answer a Plan."
  3654.  
  3655.     | currentMark constraintCount plan nextC c m |
  3656.     sortedConstraints do: [: c | c prepareForPlanning].
  3657.     currentMark _ Time millisecondClockValue.
  3658.     constraintCount _ sortedConstraints size.
  3659.     plan _ Plan new: constraintCount * 2.
  3660.     nextC _ 1.
  3661.     [nextC <= constraintCount] whileTrue:
  3662.         [c _ sortedConstraints at: nextC.
  3663.          m _ c attemptSatisfaction: currentMark.
  3664.          (m notNil)
  3665.             ifTrue:
  3666.                 [(c doesSomething) ifTrue: [plan addLast: m].
  3667.                  nextC _ 1]
  3668.             ifFalse:
  3669.                 [nextC _ nextC + 1]].
  3670.     ^plan! !
  3671.  
  3672. Object subclass: #AbstractMethod
  3673.     instanceVariableNames: 'codeString bindings '
  3674.     classVariableNames: ''
  3675.     poolDictionaries: ''
  3676.     category: 'ThingLabII-Constraints'!
  3677. AbstractMethod comment:
  3678. 'A Method is the unit of computation for a constraint. Executing the method enforces the constraint using some the constraint''s variables as inputs and computing other variables as outputs. The input and output variable sets may not intersect but either set may be empty.
  3679.  
  3680. Instance variables:
  3681.     codeString...    string that can be used to compile this method <String>
  3682.     bindings...    a string indicating the mapping of constraint variables
  3683.                 to my inputs and outputs. In this string, ''i'' indicates an
  3684.                 input, ''o'' indicates and output, and ''x'' indicates a
  3685.                 constraint variable unused by this method. <String>
  3686.     inDatas...    a cache of the ThingDatas for my inputs {ThingData}
  3687.     outDatas...    a cache of the ThingDatas of my outputs {ThingData}
  3688. '!
  3689.  
  3690.  
  3691. !AbstractMethod methodsFor: 'access'!
  3692.  
  3693. bindings
  3694.     "Answer my binding array."
  3695.  
  3696.     ^bindings!
  3697.  
  3698. bindings: anArrayOfCharacters    
  3699.     "Set my binding array."
  3700.  
  3701.     bindings _ anArrayOfCharacters.!
  3702.  
  3703. codeString
  3704.     "Answer my code string."
  3705.  
  3706.     ^codeString!
  3707.  
  3708. codeString: aString
  3709.     "Set my code string."
  3710.  
  3711.     codeString _ aString.! !
  3712.  
  3713. !AbstractMethod methodsFor: 'DeltaBlue'!
  3714.  
  3715. execute: refList
  3716.     "Execute myself to enforce my constraint. refList contains all the References for my constraint."
  3717.  
  3718.     self subclassResponsibility!
  3719.  
  3720. inDatasIn: thingDatas do: aBlock
  3721.     "Evaluate the given block for each of my input ThingDatas."
  3722.  
  3723.     | i |
  3724.     i _ bindings size.
  3725.     [i > 0] whileTrue:
  3726.         [((bindings at: i) == $i) ifTrue:
  3727.             [aBlock value: (thingDatas at: i)].
  3728.          i _ i - 1].!
  3729.  
  3730. inputsAreStayIn: thingDatas
  3731.     "Answer true if all my inputs are stay or if I have no inputs."
  3732.  
  3733.     | i |
  3734.     i _ bindings size.
  3735.     [i > 0] whileTrue:
  3736.         [((bindings at: i) == $i) ifTrue:
  3737.             [((thingDatas at: i) stay) ifFalse:
  3738.                 [^false]].
  3739.          i _ i - 1].
  3740.     ^true!
  3741.  
  3742. inputsIn: thingDatas known: currentMark
  3743.     "Answer true if all my inputs have been determined (i.e. marked with the given mark) or if I have no inputs."
  3744.  
  3745.     | i |
  3746.     i _ bindings size.
  3747.     [i > 0] whileTrue:
  3748.         [((bindings at: i) == $i) ifTrue:
  3749.             [((thingDatas at: i) mark == currentMark) ifFalse:
  3750.                 [^false]].
  3751.          i _ i - 1].
  3752.     ^true!
  3753.  
  3754. isPossibleMethodGiven: constraintStrength
  3755.     "Answer true if I am a possible method given the current walkabout strengths of my variables. Normal (non-Module) methods are always possible."
  3756.  
  3757.     ^true!
  3758.  
  3759. outDatasIn: thingDatas do: aBlock
  3760.     "Evaluate the given block for each of my output ThingDatas."
  3761.  
  3762.     | i |
  3763.     i _ bindings size.
  3764.     [i > 0] whileTrue:
  3765.         [((bindings at: i) == $o) ifTrue:
  3766.             [aBlock value: (thingDatas at: i)].
  3767.          i _ i - 1].!
  3768.  
  3769. outputsAreStayIn: thingDatas
  3770.     "Answer true if all my outputs are stay or if I have no outputs."
  3771.  
  3772.     | i |
  3773.     i _ bindings size.
  3774.     [i > 0] whileTrue:
  3775.         [((bindings at: i) == $o) ifTrue:
  3776.             [((thingDatas at: i) stay) ifFalse:
  3777.                 [^false]].
  3778.          i _ i - 1].
  3779.     ^true!
  3780.  
  3781. outputsIn: thingDatas notKnown: currentMark
  3782.     "Answer true only if none of my outputs have been determined."
  3783.  
  3784.     | i |
  3785.     i _ bindings size.
  3786.     [i > 0] whileTrue:
  3787.         [((bindings at: i) == $o) ifTrue:
  3788.             [((thingDatas at: i) mark == currentMark) ifTrue:
  3789.                 [^false]].
  3790.          i _ i - 1].
  3791.     ^true!
  3792.  
  3793. strongestOutStrengthIn: thingDatas
  3794.  
  3795.     | maxOutStrength i |
  3796.     maxOutStrength _ Strength absoluteWeakest.
  3797.     i _ bindings size.
  3798.     [i > 0] whileTrue:
  3799.         [((bindings at: i) == $o) ifTrue:
  3800.             [maxOutStrength _
  3801.                 maxOutStrength strongest:  (thingDatas at: i) walkStrength].
  3802.          i _ i - 1].
  3803.     ^maxOutStrength!
  3804.  
  3805. updateOutputsIn: thingDatas for: myConstraint stay: stayFlag
  3806.     "Update the walkabout strengths and stay flags for all my outputs and answer the list of output ThingDatas."
  3807.  
  3808.     | outs i out thisOut outStrengths |
  3809.     outs _ #().    "default return value"
  3810.     i _ bindings size.
  3811.     [i > 0] whileTrue:
  3812.         [((bindings at: i) == $o) ifTrue:
  3813.             [out _ thingDatas at: i.
  3814.              (thisOut isNil) ifTrue:
  3815.                 [thisOut _ 1.     "do this initialization on demand and once at most"
  3816.                  outs _ OrderedCollection new: 10.
  3817.                  outStrengths _ myConstraint strengthsFor: self].
  3818.              outs add: out.
  3819.              out walkStrength: (outStrengths at: thisOut).
  3820.              out stay: stayFlag.
  3821.              thisOut _ thisOut + 1].
  3822.          i _ i - 1].
  3823.     ^outs! !
  3824.  
  3825. !AbstractMethod methodsFor: 'cloning'!
  3826.  
  3827. cloneWith: cloneDictionary for: aConstraint
  3828.     "Make a clone of myself for the given constraint using the mapping given by cloneDictionary. The default is to NOT copy myself, since non-Module methods can be shared."
  3829.  
  3830.     ^self! !
  3831.  
  3832. !AbstractMethod methodsFor: 'printing'!
  3833.  
  3834. printOn: aStream
  3835.  
  3836.     aStream cr; nextPutAll: 'Method('.
  3837.     aStream nextPutAll: codeString.
  3838.     aStream nextPutAll: ')'.! !
  3839.  
  3840. Object subclass: #Thing
  3841.     instanceVariableNames: 'parents constraints thingDatas '
  3842.     classVariableNames: 'DefaultIcons '
  3843.     poolDictionaries: ''
  3844.     category: 'ThingLabII-Things'!
  3845. Thing comment:
  3846. 'A Thing has two functions:
  3847.     First, it is the grouping mechanism for the user-interface.
  3848.     Second, a Thing is a constrainable object to the planner.
  3849.  
  3850. New kinds of Things are created one of three ways:
  3851.     (A) New empty Things are created by subclassing Thing.
  3852.     (B) New Things can be created from existing Things by adding and
  3853.         removing parts.
  3854.     (C) New Things can be "compiled" from old Things. The old
  3855.         Thing is then the "construction view" for the new Thing, and
  3856.         the new Thing is the "use view" for the old.
  3857.  
  3858. A Thing must never replace its instance variables (parts), as this could leave dangling references in constraints. Compound parts are updated by recursive copying.
  3859.  
  3860. Each kind of Thing is implemented using a normal Smalltalk class and a prototype instance is stored in the class. The prototype is cloned to get new instances of that kind of thing (i.e. this is a prototype based system, rather than a class based one).
  3861.  
  3862. When a new part is added to a prototype, its class is updated by adding a named instance variable for the part and by adding access methods to get and change the value of the part. (Detail: Because adding new instance variables to a class is slow, extra instance variables are kept around. These are labeled unused1, unused2, etc.) If there are instances of the class besides the prototype, the class cannot be changed. Instead, a copy of the class and prototype are made and the new class is changed.
  3863.  
  3864. Things rely on knowing and controlling their instance variable layout. Please do not subclass a Thing or, if you must, do not add any instance variables or you will get unexpected results.
  3865.  
  3866. Instance variables:
  3867.     parents...    the parents of this Thing. There can be
  3868.                 multiple parents because of merging. {Thing}
  3869.     constraints...    the constraints owned by this Thing. Used to
  3870.                 clone constraints along with a Thing. {Constraint}
  3871.     thingData...    data structure for planning (up to one entry per sub-part)
  3872.                 {name->ThingData}
  3873.  
  3874. Class instance variables:
  3875.     thingName...        text name given by the user <String>
  3876.     partIcon...        icon for display in the parts bin <Form>
  3877.     explainText...    text description for the user <String>
  3878.     partNamesAndIndices...
  3879.                     an array of (<Symbol>,<SmallInteger>) pairs
  3880.                     used to keep track of the allocation and naming
  3881.                     of instance variables to hold parts
  3882.     externalParts...    sub-parts to be visible when this Thing is
  3883.                     compiled {Thing}
  3884.     useView...        the class of the useView if this Thing was compiled
  3885.     prototype...        an instance that is the prototype for this type
  3886.                     <some subclass of Thing>
  3887. '!
  3888.  
  3889.  
  3890. !Thing methodsFor: 'public-part add/remove'!
  3891.  
  3892. addPartsNamed: nameList toHold: partsList
  3893.     "Add a collection of new parts with the given names for the objects in partsList. Compile get and put access methods for the new parts. Answer true if I had to become a new class in order to do this. partsList may contain Strings or Symbols."
  3894.  
  3895.     | changedType partNameStrings slot |
  3896.     (self isStructureModifiable) ifFalse:
  3897.         [^nil error: 'Sorry, my structure cannot be modified'].
  3898.  
  3899.     "make a new class for me if necessary"
  3900.     BusyCursor begin.
  3901.     changedType _ false.
  3902.     (self isUnencumbered) ifFalse:
  3903.         [changedType _ true.
  3904.          self becomeUnencumbered].
  3905.  
  3906.     "allocate and initialize instance variables"
  3907.     BusyCursor inc.
  3908.     partNameStrings _ nameList collect: [: n | n asString].
  3909.     partNameStrings with: partsList do:
  3910.         [: partName : part |
  3911.          BusyCursor inc.
  3912.          "allocate a new instance variable"
  3913.          slot _ self findEmptyInstVar.
  3914.          self class renameInstVarAt: (slot - self class instOffset) as: partName.
  3915.          self class partNamesAndIndices add: (Array
  3916.             with: partName asSymbol
  3917.             with: slot).
  3918.  
  3919.          "put the new part into the new slot and make me its parent"
  3920.          self instVarAt: slot put: part.
  3921.          (part isThing) ifTrue: [part addParent: self]].
  3922.  
  3923.     "build the part access methods"
  3924.     BusyCursor inc.
  3925.     self class
  3926.         compileAccessMethodsFor: partsList
  3927.         named: nameList.
  3928.  
  3929.     BusyCursor end.
  3930.     ^changedType!
  3931.  
  3932. addThing: aThing 
  3933.     "Add a part variable with a made up name like 'numberPrinter5' and put aThing into it. This method must handle Thing names that include spaces, digits, and/or capital first letters. Answer true if I had to become a new class to accomplish this."
  3934.  
  3935.     | partName partNum |
  3936.     partName _ aThing name asString copyUpTo: $ .
  3937.     (partName isEmpty) ifTrue: [partName _ 'part'].
  3938.     partName at: 1 put: (partName at: 1) asLowercase.
  3939.     [(partName at: partName size) isDigit] whileTrue:
  3940.         [partName _ partName copyFrom: 1 to: partName size - 1].
  3941.     (partName isEmpty) ifTrue: [partName _ 'part'].
  3942.     partNum _ self findEmptyInstVar - self class instOffset.
  3943.     ^self
  3944.         addPartsNamed: (Array with: (partName, partNum printString))
  3945.         toHold: (Array with: aThing)!
  3946.  
  3947. removePartNamed: partName
  3948.     "Remove and destroy this part and its access methods. You may only remove parts from the top-level Thing."
  3949.  
  3950.     | instIndex partToRemove changedType allThingDatas |
  3951.     (self isStructureModifiable) ifFalse:
  3952.         [^self error: 'Sorry, my structure cannot be modified'].
  3953.     (parents isEmpty) ifFalse:
  3954.         [^self error: 'You may only remove top-level parts'].
  3955.  
  3956.     instIndex _
  3957.         (self class partNamesAndIndices
  3958.             detect: [: pair | pair first = partName asSymbol]
  3959.             ifNone: [^self error: partName, ' is not one of my parts']) last.
  3960.  
  3961.     BusyCursor begin.
  3962.     partToRemove _ self perform: partName asSymbol.
  3963.     changedType _ false.
  3964.     (self isUnencumbered) ifFalse: 
  3965.         [changedType _ true.
  3966.          self becomeUnencumbered].
  3967.  
  3968.     "removing a non-Thing part:"
  3969.     (partToRemove isThing) ifFalse:
  3970.         [self removeConstraintsForPart: partName.
  3971.          partToRemove release].
  3972.  
  3973.     "removing a Thing part:"
  3974.     (partToRemove isThing) ifTrue:
  3975.         ["extract the part from all external merges"
  3976.          BusyCursor inc.
  3977.          self isolate: self->partName
  3978.             within: self->partName.
  3979.  
  3980.          "remove all constraints attached to the part"
  3981.          BusyCursor inc.
  3982.          allThingDatas _ Set new.
  3983.          partToRemove allThingDatasInto: allThingDatas.
  3984.          allThingDatas do: 
  3985.             [: thingData | 
  3986.              BusyCursor inc.
  3987.              thingData constraints copy do: [: c | c removeConstraint]].
  3988.  
  3989.          "sanity check: did we get 'em all?"
  3990.          allThingDatas _ Set new.
  3991.          partToRemove allThingDatasInto: allThingDatas.
  3992.          (allThingDatas isEmpty)
  3993.             ifFalse: [self error: 'ThingLabII Internal Error'].
  3994.  
  3995.         "nil out the part instance variable and destroy the part"
  3996.         BusyCursor inc.
  3997.         partToRemove destroy].
  3998.  
  3999.     "remove the part's inst var and access methods from the class"
  4000.     BusyCursor inc.
  4001.     self instVarAt: instIndex put: nil.
  4002.     self class removePartNamed: partName asSymbol.
  4003.  
  4004.     BusyCursor end.
  4005.     ^changedType! !
  4006.  
  4007. !Thing methodsFor: 'public-merging'!
  4008.  
  4009. extractMergedPart: partRef
  4010.     "Extract the part with the given reference from the merge it is in. Answer true if I had to create a new class in order to do this. The extracted part retains all internal merges and its internally owned constraints."
  4011.  
  4012.     | changedType |
  4013.     "sanity checks"
  4014.     ((partRef topParent == self topParent) and:
  4015.      [(partRef value isThing) and:
  4016.      [partRef value parents size > 1]]) ifFalse:
  4017.         [^self error: 'attempt to unmerge parts that are not merged or that I do not own'].
  4018.     (self isStructureModifiable) ifFalse:
  4019.         [^self error: 'you cannot modify the structure of this Thing'].
  4020.  
  4021.     BusyCursor begin.
  4022.     changedType _ false.
  4023.     (self isUnencumbered) ifFalse: 
  4024.         [changedType _ true.
  4025.          self becomeUnencumbered].
  4026.  
  4027.     self extractFromMerge: partRef.
  4028.  
  4029.     BusyCursor end.
  4030.     ^changedType!
  4031.  
  4032. extractPart: partRef
  4033.     "Extract the top-most owner of this part from all merges. For example, if the given reference is for the TextThing part of a NumberPrinter, the NumberPrinter and all its sub-parts will be extracted from all merges."
  4034.  
  4035.     | changedType topRef |
  4036.     (self isStructureModifiable) ifFalse:
  4037.         [^self error: 'Sorry, my structure cannot be modified'].
  4038.     (parents isEmpty) ifFalse:
  4039.         [^self error: 'You may only remove top-level parts'].
  4040.     (partRef value isThing) ifFalse:
  4041.         [^false].        "can only extract Thing parts"
  4042.     (partRef topParent ~~ self) ifTrue:
  4043.         [^self error: 'Part is not owned by me'].
  4044.  
  4045.     BusyCursor begin.
  4046.     changedType _ false.
  4047.     (self isUnencumbered) ifFalse: 
  4048.         [changedType _ true.
  4049.          self becomeUnencumbered].
  4050.  
  4051.     "extract the part from all merges"
  4052.     topRef _ partRef copyFromTopParent.
  4053.     self isolate: topRef within: topRef.
  4054.     BusyCursor inc.
  4055.  
  4056.     BusyCursor end.
  4057.     ^changedType!
  4058.  
  4059. mergePart: part1 withPart: part2 
  4060.     "Merge two of my sub-parts. The sub-parts must be Things. Answer true if I had to become unencumbered (i.e. change my class) in order to do the merge."
  4061.  
  4062.     | changedType |
  4063.     "sanity checks"
  4064.     (self isStructureModifiable) ifFalse:
  4065.         [^self error: 'you cannot modify the structure of this Thing'].
  4066.     ((part1 isThing) & (part2 isThing)) ifFalse:
  4067.         [self error: 'you may only merge Things'].
  4068.     ((part1 topParent == self topParent) &
  4069.      (part2 topParent == self topParent)) ifFalse:
  4070.         [^self error: 'parts may be merged only if they have a common ancestor'].
  4071.  
  4072.     (part1 == part2) ifTrue:
  4073.         [^false].     "the given parts are already merged"
  4074.  
  4075.     BusyCursor begin.
  4076.     changedType _ false.
  4077.     (self isUnencumbered) ifFalse: 
  4078.         [changedType _ true.
  4079.          self becomeUnencumbered].
  4080.  
  4081.     BusyCursor inc.
  4082.     (self privateMerge: part1 into: part2) ifFalse:
  4083.         [Display reverse; reverse].
  4084.  
  4085.     BusyCursor end.
  4086.     ^changedType! !
  4087.  
  4088. !Thing methodsFor: 'public-cloning/destruction'!
  4089.  
  4090. clone
  4091.     "Answer a clone of myself. Cloning Things is done in two passes. In pass 1, we recursively copy the old Thing's part-whole structure, being careful to maintain the same graph structure for shared parts (sharing occurs when parts of the old Thing have been merged). During this first pass we also build a dictionary that maps parts in the old Thing to their corresponding parts in the new Thing. In pass 2, all constraints owned by the old Thing are cloned and and added to the new Thing, after first updating their references to point to the new Thing's parts."
  4092.  
  4093.     | cloneDictionary myClone constraintsToClone |
  4094.     cloneDictionary _ IdentityDictionary new: 200.
  4095.     myClone _ self clonePass1: cloneDictionary.
  4096.     myClone clonePass2: cloneDictionary.
  4097.     ^myClone!
  4098.  
  4099. destroy
  4100.     "Destroy myself (this instance only, not its class). Destruction helps avoid circular garbage. Warning: be sure not to destroy the prototype for a class of Things unless you know what you are doing."
  4101.  
  4102.     | part |
  4103.     (constraints notNil) ifTrue:
  4104.         [constraints do: [: constraint | constraint destroy]].
  4105.     self partIndicesDo:
  4106.         [: i |
  4107.          part _ self instVarAt: i.
  4108.          (part notNil & part isThing) ifTrue: [part destroy].
  4109.          (part notNil & part isThing not) ifTrue: [part release].
  4110.          self instVarAt: i put: nil].
  4111.     (thingDatas notNil) ifTrue:
  4112.         [thingDatas do: [: thingData | thingData destroy]].
  4113.     parents _ nil.
  4114.     constraints _ nil.
  4115.     thingDatas _ nil.!
  4116.  
  4117. destroyAndRemoveClass
  4118.     "Attempt to destroy myself and my class and answer true if successful. In other words, entirely delete all evidence of myself from the system. This can only happen if I am the only instance. This message is sent to the prototype Thing for a class of Things. "
  4119.  
  4120.     (self class allInstances size == 1) ifFalse: [^false].
  4121.     self destroy.
  4122.     self class destroy.
  4123.     ^true! !
  4124.  
  4125. !Thing methodsFor: 'public-testing'!
  4126.  
  4127. canMerge: thingOne with: thingTwo
  4128.     "Answer true if I can merge these two parts. The parts can be merged only if they both have the same topParent as me, both are Things of the same class, and they are not already merged."
  4129.  
  4130.     ^(thingOne topParent == self topParent) and:
  4131.     [(thingTwo topParent == self topParent) and:
  4132.     [(thingOne isThing & thingTwo isThing) and:
  4133.     [(thingOne class == thingTwo class) and:
  4134.     [(thingOne ~~ thingTwo)]]]]!
  4135.  
  4136. isStructureModifiable
  4137.     "Answer true if it is possible to modify my structure, even if doing so entails creating a new class. This is overridden by PrimitiveThing to prevent primitive Things from being modified."
  4138.  
  4139.     ^true!
  4140.  
  4141. isThing
  4142.     "Answer true if I am a Thing."
  4143.  
  4144.     ^true!
  4145.  
  4146. isUnencumbered
  4147.     "Answer true if I am unencumbered and thus can be freely modified. This is true if I am the only instance of my class (i.e. the prototype) and if I have no construction or use views. If I AM encumbered then you can make a new, equivalent, class using the 'becomeUnencumbered' message, and modify the prototype of the new class."
  4148.  
  4149.     ^(self class allInstances size = 1) and:
  4150.     [(self class useView isNil) and:
  4151.     [self class constructionView isNil]]!
  4152.  
  4153. isUseView
  4154.     "Answer true if I was compiled from another Thing."
  4155.  
  4156.     ^self class constructionView notNil! !
  4157.  
  4158. !Thing methodsFor: 'public-references'!
  4159.  
  4160. -> aPathSymbol
  4161.     "Answer a Reference to the part of me with the given path. The path is a possibly compound symbol such as '#a.node.lastValue'."
  4162.  
  4163.     ^Reference on: self path: aPathSymbol asSymbol path!
  4164.  
  4165. partAt: aPath
  4166.  
  4167.     | part |
  4168.     part _ self.
  4169.     aPath path do:
  4170.         [: partName |
  4171.          part _ part perform: partName].
  4172.     ^part!
  4173.  
  4174. referenceToYourself
  4175.     "Answer a Reference to myself."
  4176.  
  4177.     | aParent |
  4178.     aParent _ parents first.
  4179.     ^aParent->(aParent firstPartNameFor: self)! !
  4180.  
  4181. !Thing methodsFor: 'public-stay constraints'!
  4182.  
  4183. defaultStay: path
  4184.     "Add a default stay constraint to the given part of me. Answer the constraint."
  4185.  
  4186.     ^self addConstraint:
  4187.         (StayConstraint
  4188.             ref: self->path
  4189.             strength: #default)!
  4190.  
  4191. preferStay: path
  4192.     "Add a preferred stay constraint to the given part of me. Answer the constraint."
  4193.  
  4194.     ^self addConstraint:
  4195.         (StayConstraint
  4196.             ref: self->path
  4197.             strength: #preferred)!
  4198.  
  4199. requireStay: path
  4200.     "Add a preferred stay constraint to the given part of me. Answer the constraint."
  4201.  
  4202.     ^self addConstraint:
  4203.         (StayConstraint
  4204.             ref: self->path
  4205.             strength: #required)!
  4206.  
  4207. strongDefaultStay: path
  4208.     "Add a default stay constraint to the given part of me. Answer the constraint."
  4209.  
  4210.     ^self addConstraint:
  4211.         (StayConstraint
  4212.             ref: self->path
  4213.             strength: #strongDefault)!
  4214.  
  4215. stronglyPreferStay: path
  4216.     "Add a strongly preferred stay constraint to the given part of me. Answer the constraint."
  4217.  
  4218.     ^self addConstraint:
  4219.         (StayConstraint
  4220.             ref: self->path
  4221.             strength: #strongPreferred)!
  4222.  
  4223. weakDefaultStay: path
  4224.     "Add a weak default stay constraint to the given part of me. Answer the constraint."
  4225.  
  4226.     ^self addConstraint:
  4227.         (StayConstraint
  4228.             ref: self->path
  4229.             strength: #weakDefault)! !
  4230.  
  4231. !Thing methodsFor: 'public-equals constraints'!
  4232.  
  4233. default: pathOne equals: pathTwo
  4234.     "Add and answer a default equality constraint between the given parts of me."
  4235.  
  4236.     ^self addConstraint:
  4237.         (EqualityConstraint
  4238.             ref: self->pathOne
  4239.             ref: self->pathTwo
  4240.             strength: #default)!
  4241.  
  4242. prefer: pathOne equals: pathTwo
  4243.     "Add and answer a preferred equality constraint between the given parts of me."
  4244.  
  4245.     ^self addConstraint:
  4246.         (EqualityConstraint
  4247.             ref: self->pathOne
  4248.             ref: self->pathTwo
  4249.             strength: #preferred)!
  4250.  
  4251. require: pathOne equals: pathTwo
  4252.     "Add and answer a required equality constraint between the given parts of me."
  4253.  
  4254.     ^self addConstraint:
  4255.         (EqualityConstraint
  4256.             ref: self->pathOne
  4257.             ref: self->pathTwo
  4258.             strength: #required)!
  4259.  
  4260. stronglyPrefer: pathOne equals: pathTwo
  4261.     "Add and answer a strongly preferred equality constraint between the given parts of me."
  4262.  
  4263.     ^self addConstraint:
  4264.         (EqualityConstraint
  4265.             ref: self->pathOne
  4266.             ref: self->pathTwo
  4267.             strength: #strongPreferred)! !
  4268.  
  4269. !Thing methodsFor: 'public-other constraints'!
  4270.  
  4271. methods: methodList where: bindingsList strength: aSymbol
  4272.     "Create and add a constraint of the given strength constructed from the given set of methods. Answer the constraint constructed. See require:where: for a description of the bindingList."
  4273.  
  4274.     | variableNames pathList refs |
  4275.     variableNames _ (bindingsList collect: [: pair | pair first]) asArray.
  4276.     pathList _ (bindingsList collect: [: pair | pair last]) asArray.
  4277.     refs _ pathList collect: [: path | self->path].
  4278.     ^self addConstraint:
  4279.         (Constraint
  4280.             symbols: variableNames
  4281.             methodStrings: methodList
  4282.             refs: refs
  4283.             strength: aSymbol)!
  4284.  
  4285. offset: pathOne by: offset from: pathTwo
  4286.     "Add a strongly preferred offset constraint to make the part with pathTwo be equal to the part with pathOne plus the given offset."
  4287.  
  4288.     ^self addConstraint:
  4289.         (OffsetConstraint
  4290.             ref: self->pathTwo
  4291.             ref: self->pathOne
  4292.             strength: #strongPreferred
  4293.             offset: offset)!
  4294.  
  4295. offset: pathOne by: offset from: pathTwo strength: aSymbol
  4296.     "Add an offset constraint to make the part with pathTwo be equal to the part with pathOne plus the given offset."
  4297.  
  4298.     ^self addConstraint:
  4299.         (OffsetConstraint
  4300.             ref: self->pathTwo
  4301.             ref: self->pathOne
  4302.             strength: aSymbol
  4303.             offset: offset)!
  4304.  
  4305. prefer: anEquation where: bindingsList
  4306.     "Create and add a preferred constraint constructed from the given equation (a String). Answer the constraint constructed. See require:where: for a description of the bindingList argument."
  4307.  
  4308.     | variableNames pathList refs |
  4309.     variableNames _ (bindingsList collect: [: pair | pair first]) asArray.
  4310.     pathList _ (bindingsList collect: [: pair | pair last]) asArray.
  4311.     refs _ pathList collect: [: path | self->path].
  4312.     ^self addConstraint:
  4313.         (Constraint
  4314.             symbols: variableNames
  4315.             equation: anEquation
  4316.             refs: refs
  4317.             strength: #preferred)!
  4318.  
  4319. require: anEquation where: bindingsList
  4320.     "Create and add a required constraint constructed from the given equation (a String). Answer the constraint constructed. bindingsList is an ordered list of (variableName, part) pairs such as #((x1 a.location.x) (x2 b.location.x)). In each pair, variableName is a variable in the equation and part is a path for the part of me to which the variable should be bound."
  4321.  
  4322.     | variableNames pathList refs |
  4323.     variableNames _ (bindingsList collect: [: pair | pair first]) asArray.
  4324.     pathList _ (bindingsList collect: [: pair | pair last]) asArray.
  4325.     refs _ pathList collect: [: path | self->path].
  4326.     ^self addConstraint:
  4327.         (Constraint
  4328.             symbols: variableNames
  4329.             equation: anEquation
  4330.             refs: refs
  4331.             strength: #required)!
  4332.  
  4333. stronglyPrefer: anEquation where: bindingsList
  4334.     "Create and add a strongly preferred constraint constructed from the given equation (a String). Answer the constraint constructed. See require:where: for a description of the bindingList argument."
  4335.  
  4336.     | variableNames pathList refs |
  4337.     variableNames _ (bindingsList collect: [: pair | pair first]) asArray.
  4338.     pathList _ (bindingsList collect: [: pair | pair last]) asArray.
  4339.     refs _ pathList collect: [: path | self->path].
  4340.     ^self addConstraint:
  4341.         (Constraint
  4342.             symbols: variableNames
  4343.             equation: anEquation
  4344.             refs: refs
  4345.             strength: #strongPreferred)!
  4346.  
  4347. stronglyPreferEdit: path
  4348.     "Add a strongly preferred edit constraint to the given part of me. Answer the constraint."
  4349.  
  4350.     ^self addConstraint:
  4351.         (EditConstraint
  4352.             ref: self->path
  4353.             strength: #strongPreferred)! !
  4354.  
  4355. !Thing methodsFor: 'public-changes'!
  4356.  
  4357. set: pathSymbol to: aValue
  4358.     "Assign the given value to the subpart of this Thing with the given path using a strength of #preferred."
  4359.  
  4360.     self set: pathSymbol to: aValue strength: #preferred.!
  4361.  
  4362. set: pathSymbol to: aValue strength: strengthSymbol
  4363.     "Assign the given value to the the subpart of this Thing with the given path using the given strength."
  4364.  
  4365.     | ref editConstraint |
  4366.     ref _ self->pathSymbol.
  4367.     (ref thingData isNil or: [ref thingData determinedBy isNil])
  4368.         ifTrue:
  4369.             ["easy case: no constraint need be overridden"
  4370.              ref value: aValue.
  4371.               DeltaBluePlanner propagateFrom: ref thingData]
  4372.         ifFalse:
  4373.             ["must attempt to override other constraints on the part"
  4374.              editConstraint _ EditConstraint ref: ref strength: strengthSymbol.
  4375.              editConstraint addConstraint.
  4376.              (editConstraint isSatisfied) ifTrue:
  4377.                 [ref value: aValue.
  4378.                  DeltaBluePlanner propagateFrom: ref thingData].
  4379.              editConstraint removeConstraint; destroy].!
  4380.  
  4381. setAll: paths to: values
  4382.     "Assign the given values to the subparts of this Thing with the given paths using a strength of #preferred."
  4383.  
  4384.     self setAll: paths to: values strength: #preferred.!
  4385.  
  4386. setAll: paths to: values strength: strengthSymbol
  4387.     "Assign the given values to the subparts of this Thing with the given paths using the given strength."
  4388.  
  4389.     | refs editConstraints thisRef thisConstraint okay |
  4390.     "sanity check"
  4391.     (paths size = values size) ifFalse:
  4392.         [^self error: 'paths and values must be same size'].
  4393.  
  4394.     "build edit constraints"
  4395.     refs _ Array new: paths size.
  4396.     editConstraints _ Array new: paths size.
  4397.     1 to: paths size do:
  4398.         [: i |
  4399.          thisRef _ self->(paths at: i).
  4400.          refs at: i put: thisRef.
  4401.          thisConstraint _ EditConstraint ref: thisRef strength: strengthSymbol.
  4402.          editConstraints at: i put: thisConstraint].
  4403.  
  4404.     "add all the edit constraints"
  4405.     okay _ true.        "true iff all edit constraints are satisfied"
  4406.     editConstraints do:
  4407.         [: c |
  4408.          c addConstraint.
  4409.          (c isSatisfied) ifFalse: [okay _ false]].
  4410.  
  4411.     (okay) ifTrue:
  4412.         ["do the assignments only if all the edit constraints are satisfied"
  4413.          1 to: refs size do:
  4414.             [: i |
  4415.              thisRef _ (refs at: i).
  4416.              thisRef value: (values at: i).
  4417.              DeltaBluePlanner propagateFrom: thisRef thingData]].
  4418.  
  4419.     "remove all the edit constraints"
  4420.     editConstraints do:
  4421.         [: c | c removeConstraint; destroy].! !
  4422.  
  4423. !Thing methodsFor: 'history'!
  4424.  
  4425. advanceHistory
  4426.     "If this thing keeps previous states, then tick its 'clock' to advance the states one step. Things that don't keep history do nothing."!
  4427.  
  4428. keepsHistory
  4429.     "Some Things keep one or more previous states of some of their variables. Such Things should answer true to this message and should also implement the 'advanceHistory' message."
  4430.  
  4431.     ^false! !
  4432.  
  4433. !Thing methodsFor: 'UI-parts bin'!
  4434.  
  4435. explainText
  4436.  
  4437.     ^self class explainText!
  4438.  
  4439. explainText: aString
  4440.  
  4441.     self class explainText: aString.!
  4442.  
  4443. icon
  4444.  
  4445.     ^self class partIcon!
  4446.  
  4447. icon: aForm
  4448.  
  4449.     self class partIcon: aForm.!
  4450.  
  4451. name
  4452.  
  4453.     ^self class name!
  4454.  
  4455. name: newName
  4456.  
  4457.     (Smalltalk includesKey: newName asSymbol) ifFalse:
  4458.         [self class rename: newName].! !
  4459.  
  4460. !Thing methodsFor: 'UI-glyph access'!
  4461.  
  4462. glyphsComment
  4463.     "Many primitive Things obey the basic protocol for glyphs. That is, they may be displayed, selected, and moved. A Thing often makes all the glyphs of its component parts available for all these operations. However, sometimes a Thing may hide some of the glyphs of its components or some aspect of those glyphs, such as the ability to select them. Thus, there are different messages for collecting the glyphs of Thing for various purposes. A Thing may override the default behavior (which is to return all the glyphs of its sub-parts) to control the visibility of its sub-part's glyphs for different operations. The three categories of glyphs are:
  4464.  
  4465.     1. visible glyphs -- glyphs that are visible in the display
  4466.     2. selectable glyphs -- glyphs that can be selected and moved
  4467.     3. input glyphs -- glyphs that respond to keyboard and/or mouse events
  4468.  
  4469. These categories are orthogonal, so it is possible to have visible glyphs that cannot be selected and moved or glyphs that can be selected but are not visible (such as the end points of a PlainLine). One could extend this set of classes if necessary; these are just the categories that have been useful so far.
  4470.  
  4471. Note: If a Thing is visible, it must respond to glyph protocol. If a Thing is selectable, it must also respond to the 'location' message. If a Thing is an input glyph, it must also respond to the 'wantsKeystrokes' and 'wantsMouse' messages, and if it answers 'true' to one of these messages, it must support the corresponding keyboard or mouse prototcol."!
  4472.  
  4473. inputGlyphs
  4474.     "Answer the set of my glyphs that are candidates for mouse and/or keyboard input."
  4475.  
  4476.     | inputGlyphs |
  4477.     inputGlyphs _ OrderedCollection new.
  4478.     self inputGlyphsInto: inputGlyphs.
  4479.     ^self removeDuplicates: inputGlyphs!
  4480.  
  4481. inputGlyphsInto: aSet
  4482.     "Add all my possible input Thing parts to aSet."
  4483.  
  4484.     self thingPartsDo:
  4485.         [: p | p inputGlyphsInto: aSet].!
  4486.  
  4487. removeDuplicates: aCollection
  4488.     "Answer a copy of the given collection without duplicates. The order of the collection is maintained."
  4489.  
  4490.     | result |
  4491.     result _ aCollection species new: aCollection size.
  4492.     aCollection do:
  4493.         [: element |
  4494.          (result includes: element) ifFalse: [result add: element]].
  4495.     ^result!
  4496.  
  4497. selectableGlyphs
  4498.     "Answer the set of my glyphs that are to be selectable and moveable."
  4499.  
  4500.     | selectableGlyphs |
  4501.     selectableGlyphs _ OrderedCollection new.
  4502.     self selectableGlyphsInto: selectableGlyphs.
  4503.     ^self removeDuplicates: selectableGlyphs!
  4504.  
  4505. selectableGlyphsInto: aSet
  4506.     "Add all my selectable Thing parts to aSet."
  4507.  
  4508.     self thingPartsDo:
  4509.         [: p | p selectableGlyphsInto: aSet].!
  4510.  
  4511. visibleGlyphs 
  4512.     "Answer the set of my glyphs that are to be visible in the display."
  4513.  
  4514.     | glyphs |
  4515.     glyphs _ OrderedCollection new.
  4516.     self visibleGlyphsInto: glyphs.
  4517.     ^self removeDuplicates: glyphs!
  4518.  
  4519. visibleGlyphsInto: aSet
  4520.     "Add all my visible Thing parts to aSet."
  4521.  
  4522.     self thingPartsDo:
  4523.         [: p | p visibleGlyphsInto: aSet].! !
  4524.  
  4525. !Thing methodsFor: 'UI-glyph protocol'!
  4526.  
  4527. boundingBox
  4528.     "Answer my bounding box."
  4529.  
  4530.     ^self subclassResponsibility!
  4531.  
  4532. containsPoint: aPoint
  4533.     "More complex subclasses may refine this method."
  4534.  
  4535.     ^self boundingBox containsPoint: aPoint!
  4536.  
  4537. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox 
  4538.     "This is the generic Thing display method. Subclasses of Thing may implement more specialized display methods. This method displays all the parts of the Thing."
  4539.  
  4540.     self thingPartsDo:
  4541.         [: part |
  4542.          part
  4543.             displayOn: aDisplayMedium
  4544.             at: aDisplayPoint
  4545.             clippingBox: clipBox].!
  4546.  
  4547. glyphDependsOn
  4548.     "Answer a collection of Things whose values affect my display appearance (i.e. my glyph). By default, my display appearance does not depend on anything."
  4549.  
  4550.     ^Array new!
  4551.  
  4552. highlightOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox 
  4553.     "This is the default Thing highlighted display method. It draws a box around the Thing. Subclasses may refine."
  4554.  
  4555.     aDisplayMedium
  4556.         border: ((self boundingBox translateBy: aDisplayPoint)
  4557.                     insetOriginBy: -2 cornerBy: -2)
  4558.         widthRectangle: (1@1 corner: 1@1)
  4559.         mask: (Form black)
  4560.         clippingBox: clipBox.!
  4561.  
  4562. intersects: aRectOrThing
  4563.     "Answer true if I intersect the given object, which may be either a Rectangle or another Thing."
  4564.  
  4565.     (aRectOrThing isMemberOf: Rectangle)
  4566.         ifTrue:
  4567.             [^aRectOrThing intersects: self boundingBox]
  4568.         ifFalse:
  4569.             [^aRectOrThing boundingBox intersects: self boundingBox].!
  4570.  
  4571. location
  4572.     "Answer a PointThing that is my location. This must be implemented by any Thing that may be a selectable glyph."
  4573.  
  4574.     self subclassResponsibility! !
  4575.  
  4576. !Thing methodsFor: 'UI-keyboard'!
  4577.  
  4578. handleKeystroke: aCharacter view: aView
  4579.     "Accept the given character. The default behavior is to do nothing."!
  4580.  
  4581. keystrokeConstraints
  4582.     "Answer a list of constraints that should be added before I accept keyboard input."
  4583.  
  4584.     ^self subclassResponsibility!
  4585.  
  4586. wantsKeystrokes
  4587.     "Answer true if I want to get keyboard input. Subclasses may refine this method."
  4588.  
  4589.     ^false! !
  4590.  
  4591. !Thing methodsFor: 'UI-mouse'!
  4592.  
  4593. handleMouseDown: mousePoint view: aView
  4594.     "The mouse button has been pressed. mousePoint is in local coordinates. The default behavior is to do nothing."!
  4595.  
  4596. handleMouseMove: mousePoint view: aView
  4597.     "The message is sent repeatedly while the mouse button is pressed. mousePoint is in local coordinates. The default behavior is to do nothing."!
  4598.  
  4599. handleMouseUp: mousePoint view: aView
  4600.     "The mouse button has gone up. mousePoint is in local coordinates. The default behavior is to do nothing."!
  4601.  
  4602. mouseComment
  4603.  
  4604.     "Mouse event handling: When mouse input is initiated (with option-mouse button), the following sequence of events occurs:
  4605.     1. mouseConstraints is sent to the Thing to get a list of constraints to be added before processing mouse events. The constraints are added and, if they can all be satisfied, processing proceeds. If any of these constraints cannot be satisfied, all the constraints are removed and mouse input is aborted.
  4606.     2. handleMouseDown:view: is sent to the Thing (exactly once)
  4607.     3. handleMouseMove:view: is sent to the Thing repeatedly while the mouse is down (at least once)
  4608.     4. handleMouseUp:view: is sent to the Thing (exactly once)
  4609.     5. the constraints are removed.
  4610. All of the handleMouseXXX: messages have an argument which is the mouse position in Thing coordinates."!
  4611.  
  4612. mouseConstraints
  4613.     "Answer a list of constraints that should be added before processing mouse events."
  4614.  
  4615.     ^self subclassResponsibility!
  4616.  
  4617. wantsMouse
  4618.     "Answer true if I want to be informed of mouse activity. The default behavior is to answer false."
  4619.  
  4620.     ^false! !
  4621.  
  4622. !Thing methodsFor: 'initialize-merge'!
  4623.  
  4624. initialize
  4625.     "Initialize my Thing-related fields."
  4626.  
  4627.     parents _ Array new.
  4628.     constraints _ Array new.
  4629.     thingDatas _ Dictionary new.!
  4630.  
  4631. merge: pathOne with: pathTwo
  4632.     "Merge the two sub-parts of me with the given paths."
  4633.     "WARNING: This is meant only for use in initializing new PrimitiveThings, so sanity checks are skipped."
  4634.  
  4635.     ^self privateMerge: (self partAt: pathOne) into: (self partAt: pathTwo)! !
  4636.  
  4637. !Thing methodsFor: 'parents access'!
  4638.  
  4639. addParent: aThing
  4640.     "Add the given Thing to my list of parents."
  4641.     "Details: The instance variable 'parents' is an array of Things. Due to merges, a Thing may have several parents. Each parent appears only once in the parents array (since we do not allow merges between the immediate children of a Thing, it should never be requested to have the same parent appear more than once anyhow)."
  4642.  
  4643.     (parents includes: aThing) ifFalse:
  4644.         [parents _ parents copyWith: aThing].!
  4645.  
  4646. allPartNamesFor: anObject
  4647.     "Answer all the parts names for the given object in this Thing. (Due to merges, there may be more than one). Raise an error if anObject is not one of my parts."
  4648.  
  4649.     | names |
  4650.     names _ OrderedCollection new: 10.
  4651.     self partsAndNamesDo:
  4652.         [: part : name |
  4653.          (part == anObject) ifTrue: [names add: name]].
  4654.  
  4655.     (names isEmpty) ifTrue:
  4656.         [^self error:
  4657.          'ThingLab Internal Error: the given object is not one of my parts'].
  4658.  
  4659.     ^names!
  4660.  
  4661. allTopParentPaths
  4662.     "Answer a collection of all paths from my top-most parent to me. A path is an OrderedCollection of Symbols. If I have no parents, answer a collection containing one path, the empty path."
  4663.  
  4664.     | allPaths pathsToParent thisPath |
  4665.     (parents isEmpty) ifTrue:    "no parents, so answer includes just the empty path"
  4666.         [^OrderedCollection with: OrderedCollection new].
  4667.  
  4668.     allPaths _ OrderedCollection new.
  4669.     parents do:
  4670.         [: parent |
  4671.          pathsToParent _ parent allTopParentPaths.
  4672.          (parent allPartNamesFor: self) do:
  4673.             [: nameInParent |
  4674.              pathsToParent do:
  4675.                 [: path |
  4676.                  thisPath _ path copy addLast: nameInParent; yourself.
  4677.                  allPaths add: thisPath]]].
  4678.     ^allPaths!
  4679.  
  4680. firstPartNameFor: anObject
  4681.     "Answer the name of the first part containing the given object. Raise an error if anObject is not one of my parts."
  4682.  
  4683.     self partsAndNamesDo:
  4684.         [: part : name |
  4685.          (part == anObject) ifTrue: [^name]].
  4686.  
  4687.     ^nil error: 'ThingLab Internal Error: the given object is not one of my parts'!
  4688.  
  4689. parents
  4690.     "Answer my parents array. See the comment at addParent: for a description of the structure of this array."
  4691.  
  4692.     ^parents!
  4693.  
  4694. removeParent: aThing
  4695.     "Remove aThing from my list of parents."
  4696.  
  4697.     parents _ parents copyWithout: aThing.!
  4698.  
  4699. topParent
  4700.     "Answer my top-most parent. If I have no parents, answer myself."
  4701.  
  4702.     parents isEmpty
  4703.         ifTrue: [^self]
  4704.         ifFalse: [^parents first topParent].! !
  4705.  
  4706. !Thing methodsFor: 'thingdata access'!
  4707.  
  4708. allThingDatasInto: aSet
  4709.     "Add to aSet all thingDatas attached me and to my subparts."
  4710.  
  4711.     | myThingData |
  4712.     myThingData _ self thingDataForYourself.
  4713.     (myThingData notNil) ifTrue: [aSet add: myThingData].
  4714.     aSet addAll: thingDatas.
  4715.     self allThingsDo:
  4716.         [: part |
  4717.          (part thingDatas notNil) ifTrue:
  4718.             [aSet addAll: part thingDatas]].!
  4719.  
  4720. cleanUpThingDataFor: partName 
  4721.     "Remove the ThingData for this part of me if and only if it is no longer used by any constraint. This is complicated if the part is merged because there may be pointers to its ThingData in the thingData Dictionaries of its other parents."
  4722.  
  4723.     | thingData part nameInParent |
  4724.     thingData _ self thingDataFor: partName.
  4725.     (thingData isNil or: [thingData constraints size > 0]) ifTrue:
  4726.         [^self].    "thingData is already gone or is still in use"
  4727.  
  4728.     part _ self perform: partName asSymbol.
  4729.     (part isThing) ifTrue:
  4730.         [part parents do:
  4731.             [: parent |
  4732.              (parent allPartNamesFor: part) do:
  4733.                 [: nameInParent |
  4734.                  parent localRemoveThingDataFor: nameInParent]]].
  4735.  
  4736.     self localRemoveThingDataFor: partName.!
  4737.  
  4738. localRemoveThingDataFor: partName
  4739.     "Remove and destroy the local ThingData record, if any, for the part with the given name."
  4740.  
  4741.     | thingData |
  4742.     thingData _ thingDatas removeKey: partName asSymbol ifAbsent: [nil].
  4743.     (thingData notNil) ifTrue: [thingData destroy].!
  4744.  
  4745. localThingDataFor: partSymbol
  4746.     "Answer the ThingData entry for this part of me from my local dictionary or nil if there isn't one."
  4747.  
  4748.     ^thingDatas at: partSymbol ifAbsent: [nil]!
  4749.  
  4750. strengthFor: partName
  4751.     "Answer the walkabout strength for this part of me. If there is no thingData for the given part, answer (Strength absoluteWeakest)."
  4752.  
  4753.     | thingData |
  4754.     thingData _ self thingDataFor: partName.
  4755.     (thingData isNil)
  4756.         ifTrue: [^Strength absoluteWeakest]
  4757.         ifFalse: [^thingData walkStrength].!
  4758.  
  4759. thingDataFor: partName 
  4760.     "Answer the ThingData for this part of me. If there isn't one locally, look for one among the part's other parents, in case the part participates in a merge. If we find one, make a local pointer to it for faster access in the future."
  4761.  
  4762.     | partSymbol part thingData |
  4763.     partSymbol _ partName asSymbol.
  4764.  
  4765.     "look for a ThingData locally and answer it if we find one"
  4766.     thingData _ self localThingDataFor: partSymbol.
  4767.     (thingData notNil) ifTrue: [^thingData].
  4768.  
  4769.     "if the part isn't a Thing then I am its only parent (only Things can be merged) so it has no ThingData"
  4770.     part _ self perform: partSymbol.
  4771.     (part isThing) ifFalse: [^nil].    "no ThingData found"
  4772.  
  4773.     "otherwise, look for a thingData in some other parent of the (Thing) part"
  4774.     part parents do:
  4775.         [: parent |
  4776.          (parent allPartNamesFor: part) do:
  4777.             [: nameInParent |
  4778.              thingData _ parent localThingDataFor: nameInParent.
  4779.              "if we find a ThingData, cache a pointer to it locally and answer it"
  4780.              (thingData notNil) ifTrue:
  4781.                 [thingDatas at: partSymbol put: thingData.
  4782.                   ^thingData]]].
  4783.  
  4784.      ^nil        "no ThingData found"!
  4785.  
  4786. thingDataForYourself
  4787.     "Answer a ThingData for me, if there is one."
  4788.  
  4789.     | aParent |
  4790.     (parents isEmpty) ifTrue: [^nil].    "no parents"
  4791.     aParent _ parents first.
  4792.     ^aParent thingDataFor: (aParent firstPartNameFor: self)!
  4793.  
  4794. thingDataOrAllocateFor: partName
  4795.     "Answer the ThingData structure for this part of me. If there isn't one locally, search among all the part's immediate parents to find one. If we find one, make a local pointer to it. If we don't find one, allocate a new ThingData locally."
  4796.  
  4797.     | thingData |
  4798.     thingData _ self thingDataFor: partName.
  4799.  
  4800.     "if we there is currently no ThingData for this part, allocate one"
  4801.     (thingData isNil) ifTrue:
  4802.         [thingData _ ThingData new].
  4803.  
  4804.     "store a pointer to the thingData locally and answer it"
  4805.     thingDatas at: partName asSymbol put: thingData.
  4806.     ^thingData!
  4807.  
  4808. thingDatas
  4809.     "Answer my ThingData dictionary. The entries of this dictionary map the part names (Symbols) of my constrained parts to ThingData objects."
  4810.  
  4811.     ^thingDatas! !
  4812.  
  4813. !Thing methodsFor: 'constraints'!
  4814.  
  4815. addConstraint: aConstraint
  4816.     "Add the given constraint to the set of constraints that I own and satisfy it. Answer the constraint."
  4817.  
  4818.     constraints _ constraints copyWith: aConstraint.
  4819.     aConstraint addConstraint.
  4820.     ^aConstraint!
  4821.  
  4822. constraints
  4823.     "Answer the set of constraints that I own."
  4824.  
  4825.     ^constraints!
  4826.  
  4827. constraints: newConstraints
  4828.  
  4829.     constraints _ newConstraints.!
  4830.  
  4831. removeConstraint: aConstraint
  4832.     "Remove the given constraint from the data flow and from the set of constraints that I own."
  4833.  
  4834.     aConstraint removeConstraint.
  4835.     constraints _ constraints copyWithout: aConstraint.! !
  4836.  
  4837. !Thing methodsFor: 'enumerating'!
  4838.  
  4839. allThingsDo: aBlock
  4840.     "Evaluate aBlock on me and each of my Thing subparts, recursively."
  4841.  
  4842.     self thingPartsDo: [: p | p allThingsDo: aBlock].
  4843.     aBlock value: self.!
  4844.  
  4845. partIndicesDo: aBlock
  4846.     "Do aBlock for each of my part variable indices."
  4847.  
  4848.     self class partNamesAndIndices do:
  4849.         [: nameAndIndex |
  4850.          aBlock value: (nameAndIndex at: 2)].!
  4851.  
  4852. partsAndNamesDo: aBlock
  4853.     "Do aBlock for each of my parts and its name."
  4854.  
  4855.     | name part |
  4856.     self class partNamesAndIndices do:
  4857.         [: nameAndIndex |
  4858.          name _ (nameAndIndex at: 1).
  4859.          part _ self instVarAt: (nameAndIndex at: 2).
  4860.          aBlock value: part value: name].!
  4861.  
  4862. thingPartsAndNamesDo: aBlock
  4863.     "Do aBlock for each of my Thing parts and its name."
  4864.  
  4865.     | name part |
  4866.     self class partNamesAndIndices do:
  4867.         [: nameAndIndex |
  4868.          name _ (nameAndIndex at: 1).
  4869.          part _ self instVarAt: (nameAndIndex at: 2).
  4870.          (part isThing) ifTrue: [aBlock value: part value: name]].!
  4871.  
  4872. thingPartsDo: aBlock
  4873.     "Do aBlock for each of my Thing parts."
  4874.  
  4875.     | part |
  4876.     self class partNamesAndIndices do:
  4877.         [: nameAndIndex |
  4878.          part _ self instVarAt: (nameAndIndex at: 2).
  4879.          (part isThing) ifTrue: [aBlock value: part]].! !
  4880.  
  4881. !Thing methodsFor: 'modification'!
  4882.  
  4883. allocateNewInstVars
  4884.     "Allocate a gaggle of new instance variables for my class. The variables will be given names such as 'unused13'."
  4885.  
  4886.     | oldInstVarCount increment newVars |
  4887.     oldInstVarCount _ self class instVarNames size.
  4888.     increment _ oldInstVarCount min: 64.
  4889.     newVars _ ''.
  4890.     oldInstVarCount + 1 to: oldInstVarCount + increment do:
  4891.         [: i | newVars _ newVars, 'unused' , i printString, ' '].
  4892.  
  4893.     "By luck it turns out that the addInstVarName: message works with a string containing multiple instance variables."
  4894.     self class addInstVarName: newVars.!
  4895.  
  4896. becomeUnencumbered
  4897.     "This method clones the class of this Thing to create an identical, but unused, class and prototype. This is used when we wish to modify classes that have existing instances. NOTE: The class of the receiver of this message changes as a side effect!!"
  4898.  
  4899.     | newName newThingClass cloneDict myClone newPrototype part |
  4900.     "sanity checks"
  4901.     (parents size == 0) ifFalse:
  4902.         [^self error: 'ThingLab Internal Error --
  4903. this Thing is supposed to be a prototype;
  4904. it should not have parents'].
  4905.  
  4906.     "make a copy of my class, give it a new class name and a new parts bin name, and classify it in the Smalltalk system dictionary."
  4907.     newName _ self class successorName asSymbol.
  4908.     (Smalltalk includesKey: newName) ifTrue:
  4909.         [^self error: 'The class name ''', newName, ''' is already used.'].
  4910.     newThingClass _ self class copy.
  4911.     newThingClass organization: self class organization deepCopy.
  4912.     newThingClass smashName: newName.
  4913.     Smalltalk at: newName put: newThingClass.
  4914.     SystemOrganization
  4915.         classify: newName
  4916.         under: 'Things-Built' asSymbol.
  4917.     newThingClass initializeByCopying: self class.
  4918.  
  4919.     "create a prototype instance for the new class, and then make a copy of myself to become the prototype for the new class. This is a four step process:
  4920.         1. create an instance of the new class
  4921.         2. clone my structure and values (using clonePass1:)
  4922.         3. copy the clone's variables to the instance (thus making it the equivalent of my clone but having the new class)
  4923.         4. clone my constraints to the class instance (using clonePass2:)"
  4924.  
  4925.     "clone my structure and values"
  4926.     cloneDict _ IdentityDictionary new: 200.
  4927.     myClone _ self clonePass1: cloneDict.
  4928.  
  4929.     "make a thing of the new class and copy the clone's top parts into it"
  4930.     newPrototype _ newThingClass basicNew initialize.
  4931.     1 to: self class instSize do: [: index |
  4932.         part _ myClone instVarAt: index.
  4933.         newPrototype instVarAt: index put: part.
  4934.         (part isThing) ifTrue:
  4935.             ["I will the parent after the 'become:' coming up"
  4936.              part removeParent: myClone.
  4937.              part addParent: self]].
  4938.  
  4939.     "copy the constraints to the new thing"
  4940.     newPrototype constraints: (NeedToClone with: self constraints).
  4941.     cloneDict at: self put: self.    "this is because of the 'become:' coming up"
  4942.     newPrototype clonePass2: cloneDict.
  4943.  
  4944.     "fix up the prototypes for life after the 'become:'"
  4945.     newThingClass prototype: self.
  4946.     self class prototype: newPrototype.
  4947.  
  4948.     "finally, I become the new prototype, and he becomes me"
  4949.     self become: newPrototype.!
  4950.  
  4951. findEmptyInstVar
  4952.     "Answer the index of an unused instance variable in my class. Use one of the pre-allocated instance variables if possible, otherwise allocate some more and try again."
  4953.  
  4954.     | partsSet allInstVars |
  4955.     partsSet _ Set new: 40.
  4956.     self class partNamesAndIndices do:
  4957.         [: entry | partsSet add: entry first asString].
  4958.     allInstVars _ self class instVarNames.
  4959.     1 to: allInstVars size do:
  4960.         [: i |
  4961.          (partsSet includes: (allInstVars at: i))
  4962.             ifFalse: [^i + self class instOffset]].        "found a free inst var"
  4963.  
  4964.     "allocate some new instance variables and try again"
  4965.     self allocateNewInstVars.
  4966.     ^self findEmptyInstVar! !
  4967.  
  4968. !Thing methodsFor: 'cloning'!
  4969.  
  4970. clonePass1: cloneDictionary 
  4971.     "Recursively clone myself and each of my parts, recording all clones in the given clone dictionary. If I am already in the clone dictionary, then answer a pointer to my clone, rather than copying myself again; this will preserve the acyclic structure of the sub-part graph. This operation copies the part-whole structure of a Thing and establishes its parent pointers but it does not copy the constraints or ThingData dictionaries."
  4972.  
  4973.     | myClone oldPart newPart |
  4974.     myClone _ cloneDictionary at: self ifAbsent: [nil].
  4975.     (myClone notNil) ifTrue: [^myClone].    "I've already been cloned"
  4976.  
  4977.     myClone _ self shallowCopy initialize.
  4978.     myClone constraints: (NeedToClone with: constraints).
  4979.     self partIndicesDo:
  4980.         [: i |
  4981.          oldPart _ self instVarAt: i.
  4982.          (oldPart isThing)
  4983.             ifTrue:
  4984.                 [newPart _ oldPart clonePass1: cloneDictionary.
  4985.                   newPart addParent: myClone]
  4986.             ifFalse: [newPart _ oldPart copy].
  4987.          myClone instVarAt: i put: newPart].
  4988.     cloneDictionary at: self put: myClone.
  4989.     ^myClone!
  4990.  
  4991. clonePass2: cloneDictionary
  4992.     "Clone my constraints. This method executes in the context of the newly forming clone. Because there may be multiple paths to a part and we don't wish to clone a set of constraints multiple times, the NeedToClone class is used to mark constraints that have not yet been cloned. If we encounter a part who's constraints instance variable is not marked with a 'NeedToClone' then we need not look at its sub-parts."
  4993.  
  4994.     | newC |
  4995.     (constraints isMemberOf: NeedToClone) ifTrue:
  4996.         [constraints _ constraints data collect:
  4997.             [: c |
  4998.              newC _ c cloneUsing: cloneDictionary.
  4999.              newC addConstraint.
  5000.              newC].
  5001.          self thingPartsDo: [: p | p clonePass2: cloneDictionary]].! !
  5002.  
  5003. !Thing methodsFor: 'merging'!
  5004.  
  5005. change: thingOne to: thingTwo
  5006.     "Replace all my references to thingOne with references to thingTwo."
  5007.  
  5008.     self partIndicesDo:
  5009.         [: i |
  5010.          ((self instVarAt: i) == thingOne) ifTrue:
  5011.             [self instVarAt: i put: thingTwo]].!
  5012.  
  5013. conflictsBetween: partOne and: partTwo
  5014.     "We intend to merge the given parts. Look for required-constraint conflicts between the parts themselves and all the corresponding parts of their sub-part trees and answer true if a conflict is discovered. The parts are assumed to be Things of the same class."
  5015.     "NOTE: We do NOT check for potential cycle conflicts."
  5016.  
  5017.     ^(self
  5018.         thingData: partOne thingDataForYourself
  5019.         conflictsWith: partTwo thingDataForYourself) or:
  5020.       [self subPartConflictsBetween: partOne and: partTwo]!
  5021.  
  5022. externalConstraintsFor: aThing
  5023.     "Answer the set of constraints pointing to but not owned by aThing and/or its subparts."
  5024.  
  5025.     | ownedConstraints allConstraints thingData |
  5026.     ownedConstraints _ IdentitySet new.
  5027.     allConstraints _ IdentitySet new.
  5028.     aThing allThingsDo:
  5029.         [: aThing |
  5030.          ownedConstraints addAll: aThing constraints.
  5031.          aThing thingDatas do:
  5032.             [: thingData |
  5033.              allConstraints addAll: thingData constraints]].
  5034.  
  5035.     "add top-level constraints to allConstraints"
  5036.     thingData _ aThing thingDataForYourself.
  5037.     (thingData notNil) ifTrue:
  5038.         [allConstraints addAll: thingData constraints].
  5039.  
  5040.     "external constraints = allConstraints - ownedConstraints"
  5041.     ^allConstraints select: [: c | (ownedConstraints includes: c) not]!
  5042.  
  5043. privateMerge: partOne into: partTwo
  5044.     "Merge partOne with partTwo and answer true if the operation succeeds. The parts must share a common ancestor. After the merge, partOne will be discarded."
  5045.  
  5046.     "Here is an outline the merge operation:
  5047.     1. A check is made of all thingDatas for corresponding pairs
  5048.        of sub-parts to be sure that no required constraint conflicts
  5049.        would be caused by the merge.
  5050.     2. Constraints external (i.e. not owned by any sub-part)
  5051.        to both part trees are collected and temporarily removed.
  5052.     3. The pointers to partOne in its parent are pointed to partTwo.
  5053.     4. The parents of partOne are added to partTwo.
  5054.     5. partOne is destroyed (but not its subparts, which may still be in use!!)
  5055.     6. The constraints collected in step 2 are re-added."
  5056.  
  5057.     | removedConstraints |
  5058.     "step 1"
  5059.     (self conflictsBetween: partOne and: partTwo) ifTrue:
  5060.         [^false].    "merging failed"
  5061.  
  5062.     "step 2"
  5063.     removedConstraints _ IdentitySet new.
  5064.     removedConstraints addAll: (self externalConstraintsFor: partOne).
  5065.     removedConstraints addAll: (self externalConstraintsFor: partTwo).
  5066.     removedConstraints do:
  5067.         [: constraint |
  5068.          constraint removeConstraint].
  5069.  
  5070.     "steps 3 and 4"
  5071.     (partOne parents copy) do:
  5072.         [: parent |
  5073.          parent change: partOne to: partTwo.
  5074.          partTwo addParent: parent.
  5075.          partOne removeParent: parent].
  5076.  
  5077.     "step 5"
  5078.     "protect subparts from destruction; they may still be in use"
  5079.     partOne partIndicesDo: [: i | partOne instVarAt: i put: nil].
  5080.     partOne destroy.
  5081.  
  5082.     "step 6"
  5083.     removedConstraints do:
  5084.         [: constraint | constraint addConstraint].
  5085.  
  5086.     "merging was successful"
  5087.     ^true!
  5088.  
  5089. subPartConflictsBetween: thingOne and: thingTwo
  5090.     "Check for required-constraint conflicts between the corresponding sub-parts of thingOne and thingTwo and answer true if a conflict is discovered. thingOne and thingTwo are assumed to be Things of the same class."
  5091.  
  5092.     thingOne partsAndNamesDo:
  5093.         [: part : name |
  5094.          (self
  5095.             thingData: (thingOne thingDataFor: name)
  5096.             conflictsWith: (thingTwo thingDataFor: name)) ifTrue:
  5097.                 [^true].
  5098.          (part isThing) ifTrue:
  5099.             [(self
  5100.                 subPartConflictsBetween: part
  5101.                 and: (thingTwo perform: name)) ifTrue:
  5102.                     [^true]]].
  5103.  
  5104.     "no conflicts found"
  5105.     ^false!
  5106.  
  5107. thingData: thingDataOne conflictsWith: thingDataTwo
  5108.     "Answer true if a required-constraint conflict exists between the given ThingDatas for parts we propose to merge."
  5109.  
  5110.     "no conflicts if one part is unconstrained"
  5111.     (thingDataOne isNil | thingDataTwo isNil) ifTrue: [^false].
  5112.  
  5113.     "is there a required constraint conflict?"
  5114.     ((thingDataOne walkStrength == Strength required) &
  5115.      (thingDataTwo walkStrength == Strength required)) ifTrue: [^true].
  5116.  
  5117.     "no conflicts"
  5118.     ^false! !
  5119.  
  5120. !Thing methodsFor: 'unmerging/removing'!
  5121.  
  5122. extractFromMerge: thingRef
  5123.     "The part pointed to by thingRef will be extracted from the merge that it is in. This method only unmerges at the level of thingRef; it does not unmerge merged sub-parts."
  5124.     "Details: When unmerging, we must separate the constraints attached to what used to be the single, merged part. After the unmerge, some of these constraints will continue to point to the old part, some will point to the new part, and some will point to both parts. This process is implemented by removing all the constraints that touch the merged part and reinstating them after the unmerge. Because the constraints have built-in references, they will be reinstated in their correct locations."
  5125.  
  5126.     | parent oldPart removedConstraints cloneDict newPart |
  5127.     parent _ thingRef finalVariable.
  5128.     oldPart _ thingRef value.
  5129.  
  5130.     "remove all constraints for the merge and remember them"
  5131.     removedConstraints _
  5132.         parent removeConstraintsForPart: thingRef part.
  5133.  
  5134.     "clone a copy of the old part to become the new part"
  5135.     "(the clone will get copies of all constraints owned by the part)"
  5136.     BusyCursor inc.
  5137.     newPart _ oldPart clone.
  5138.  
  5139.     "insert newPart into its parent and fix the parents of both parts"
  5140.     BusyCursor inc.
  5141.     parent change: oldPart to: newPart.
  5142.     oldPart removeParent: parent.
  5143.     newPart addParent: parent.
  5144.  
  5145.     "reinstate the constraints"
  5146.     removedConstraints do:
  5147.         [: c |
  5148.          BusyCursor inc.
  5149.          c addConstraint].!
  5150.  
  5151. isolate: thingRef within: rootRef
  5152.     "Isolate the sub-parts tree for the Thing pointed to by thingRef from all merges external to rootRef. Used when removing a part that might be merged with some other parts."
  5153.  
  5154.     | top thing internalRef externalRef |
  5155.     thingRef refresh.
  5156.     top _ thingRef topParent.
  5157.     thing _ thingRef value.
  5158.  
  5159.     "look for an external reference to me"
  5160.      externalRef _ nil.
  5161.      (thing allTopParentPaths) do:
  5162.         [: path |
  5163.          (rootRef isPrefixOf: path) ifFalse:
  5164.             [externalRef _ (Reference on: top path: path)]].
  5165.  
  5166.     "if there was an external reference then, extract myself from the merge"
  5167.      (externalRef notNil) ifTrue:
  5168.         [self extractFromMerge: thingRef].
  5169.  
  5170.     "do the same for my sub-parts"
  5171.     thing thingPartsAndNamesDo:
  5172.         [: part : partName |
  5173.          self
  5174.             isolate: (thingRef, (Array with: partName))
  5175.             within: rootRef].!
  5176.  
  5177. removeConstraintsForPart: partName
  5178.     "Remove all constraints for the part of me with the given name and all its sub-parts and add the removed constraints to the given set."
  5179.  
  5180.     | allConstraints thingData part |
  5181.     allConstraints _ IdentitySet new.
  5182.  
  5183.     "collect top-level constraints"
  5184.     thingData _ self thingDataFor: partName.
  5185.     (thingData notNil) ifTrue:
  5186.         [allConstraints addAll: thingData constraints].
  5187.  
  5188.     "collect sub-part constraints"
  5189.     part _ self perform: partName asSymbol.
  5190.     (part isThing) ifTrue:
  5191.         [part allThingsDo:
  5192.             [: subPart |
  5193.              subPart thingDatas do:
  5194.                 [: thingData |
  5195.                  allConstraints addAll: thingData constraints]]].
  5196.  
  5197.     "remove the collected constraints"
  5198.     allConstraints do:
  5199.         [: c |
  5200.          BusyCursor inc.
  5201.          c removeConstraint].
  5202.  
  5203.     ^allConstraints! !
  5204.  
  5205. !Thing methodsFor: 'printing'!
  5206.  
  5207. definitionString
  5208.     "Answer a string containing my definition for the Thing definer."
  5209.  
  5210.     | out |
  5211.     out _ (String new: 200) writeStream.
  5212.     out nextPutAll: self name; cr.
  5213.     self partsAndNamesDo:
  5214.         [: part : name |
  5215.          out tab; nextPutAll: name, ': '.
  5216.          out nextPutAll: part class name; cr].
  5217.     ^out contents!
  5218.  
  5219. longPrintOn: aStream
  5220.  
  5221.     aStream nextPutAll: '('.
  5222.     self shortPrintOn: aStream.
  5223.     self partsAndNamesDo:
  5224.         [: part : partName |
  5225.          aStream space.
  5226.          aStream nextPutAll: partName.
  5227.          aStream nextPut: $:.
  5228.          ((self thingDataFor: partName) notNil) ifTrue:
  5229.             [aStream nextPut: $:].
  5230.          part printOn: aStream].
  5231.     aStream nextPutAll: ')'.!
  5232.  
  5233. printOn: aStream
  5234.  
  5235.     (Sensor leftShiftDown)
  5236.         ifTrue: [self longPrintOn: aStream]
  5237.         ifFalse: [self shortPrintOn: aStream].!
  5238.  
  5239. shortPrintOn: aStream
  5240.  
  5241.     aStream nextPutAll: self class name, '(', self hash printString, ')'.! !
  5242. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  5243.  
  5244. Thing class
  5245.     instanceVariableNames: 'partIcon explainText partNamesAndIndices externalParts useView prototype '!
  5246.  
  5247.  
  5248. !Thing class methodsFor: 'class initialization'!
  5249.  
  5250. initialize
  5251.     "Thing initialize"
  5252.  
  5253.     "DefaultIcons holds default PartsBin icons (gizmos)."
  5254.     DefaultIcons _ OrderedCollection new.
  5255.     DefaultIcons add: (Form
  5256.         extent: 16@16
  5257.         fromArray: #(6112 10256 18448 18400 19012 19018 19066 522 634 586 580 2016 2576 5128 10756 16380)
  5258.         offset: 0@0).
  5259.     DefaultIcons add: (Form
  5260.         extent: 16@16
  5261.         fromArray: #(24582 40953 40953 25158 576 576 1504 1824 2160 3024 7688 4344 10116 15372 16634 32766)
  5262.         offset: 0@0).
  5263.     DefaultIcons add: (Form
  5264.         extent: 16@16
  5265.         fromArray: #(8 24604 61474 51228 17416 9212 32766 49155 38229 32769 32769 32769 38937 42021 26598 6168)
  5266.         offset: 0@0).
  5267.     DefaultIcons add: (Form
  5268.         extent: 16@16
  5269.         fromArray: #(32766 49155 37137 43689 37137 49155 32766 20490 20490 20490 20490 20490 21034 36185 33089 32318)
  5270.         offset: 0@0).
  5271.     DefaultIcons add: (Form
  5272.         extent: 16@16
  5273.         fromArray: #(1160 2740 4546 992 3640 7148 4644 15342 10570 14670 320 320 320 16254 24579 16382)
  5274.         offset: 0@0).
  5275.     DefaultIcons add: (Form
  5276.         extent: 16@16
  5277.         fromArray: #(0 0 0 0 0 0 0 56 124 7422 16129 32725 32929 43711 32992 65408)
  5278.         offset: 0@0).
  5279.  
  5280.     DefaultIcons _ DefaultIcons asArray.! !
  5281.  
  5282. !Thing class methodsFor: 'defining'!
  5283.  
  5284. defineNewThing
  5285.     "Create a new subclass of Thing for a new type of Thing. Give the new Thing a name like 'Thing45'. Answer the prototype instance of the new Thing."
  5286.  
  5287.     ^self defineNewThingNamed: ('Thing', ThingLabII uniqueNumber printString)!
  5288.  
  5289. defineNewThingNamed: newThingName
  5290.     "Create a new subclass of Thing for a new type of Thing. Give the new Thing the given name. Answer the prototype instance of the new Thing's class."
  5291.  
  5292.     | className newThingClass |
  5293.     className _ ((Smalltalk includesKey: newThingName)
  5294.         ifTrue: [newThingName, 'v', ThingLabII uniqueNumber printString]
  5295.         ifFalse: [newThingName]) asSymbol.
  5296.  
  5297.     BusyCursor begin.
  5298.     newThingClass _ Thing
  5299.         subclass: className
  5300.         instanceVariableNames: 'unused1 unused2 unused3 unused4 unused5 unused6 unused7 unused8 unused9 unused10 unused11 unused12 unused13 unused14 unused15 unused16'
  5301.         classVariableNames: ''
  5302.         poolDictionaries: ''
  5303.         category: 'Things-Built'.
  5304.  
  5305.     BusyCursor inc.
  5306.     newThingClass initializeBuiltThing.
  5307.  
  5308.     BusyCursor end.
  5309.     ^newThingClass prototype!
  5310.  
  5311. defineNewThingNamed: newThingName withParts: nameList toHold: partsList
  5312.     "Create a new subclass of Thing for a new type of Thing with the given parts. Give the new Thing the given name. Answer the prototype instance of the new Thing's class."
  5313.  
  5314.     | className newThingClass parts proto |
  5315.     className _ ((Smalltalk includesKey: newThingName asSymbol)
  5316.         ifTrue: [newThingName, 'v', ThingLabII uniqueNumber printString]
  5317.         ifFalse: [newThingName]) asSymbol.
  5318.  
  5319.     parts _ (String new: 100) writeStream.
  5320.     nameList do: [: part | parts nextPutAll: part; space].
  5321.     newThingClass _ Thing
  5322.         subclass: className
  5323.         instanceVariableNames: parts contents
  5324.         classVariableNames: ''
  5325.         poolDictionaries: ''
  5326.         category: 'Things-Built'.
  5327.  
  5328.     newThingClass initializeBuiltThing.
  5329.     proto _ newThingClass prototype.
  5330.     proto addPartsNamed: nameList toHold: partsList.
  5331.     ^newThingClass prototype!
  5332.  
  5333. defineNewThingWithParts: nameList toHold: partsList
  5334.     "Create a new subclass of Thing for a new type of Thing with the given parts. Answer the prototype instance of the new Thing's class."
  5335.  
  5336.     ^self
  5337.         defineNewThingNamed: ('Thing', ThingLabII uniqueNumber printString)
  5338.         withParts: nameList
  5339.         toHold: partsList! !
  5340.  
  5341. !Thing class methodsFor: 'instance creation'!
  5342.  
  5343. cloneFor: aThing
  5344.     "Answer a copy of my prototype to be used as a sub-part of aThing (i.e. aThing will be made a parent of the copy). This method is 'syntactic sugar' for building the structure of primitive Things."
  5345.  
  5346.     ^(self prototype clone) addParent: aThing!
  5347.  
  5348. new
  5349.     "Answer a copy of my prototype."
  5350.  
  5351.     ^self prototype clone! !
  5352.  
  5353. !Thing class methodsFor: 'access'!
  5354.  
  5355. basicPrototype
  5356.     "Answer the contents of my prototype field. Do not create a new prototype."
  5357.  
  5358.     ^prototype!
  5359.  
  5360. constructionView
  5361.     "Answer the class of the Thing that was compiled to create me. Non-module Things have no construction view, so answer nil. This method is overridden in ModuleThing class."
  5362.  
  5363.     ^nil!
  5364.  
  5365. constructionView: aThingClass
  5366.     "Set the class of the Thing that was compiled to create me."
  5367.  
  5368.     self subclassResponsibility!
  5369.  
  5370. explainText
  5371.     "Answer my explanation."
  5372.  
  5373.     ^explainText!
  5374.  
  5375. explainText: aString
  5376.     "Set my explanation."
  5377.  
  5378.     explainText _ aString.!
  5379.  
  5380. externalParts
  5381.     "Answer my set of external parts."
  5382.  
  5383.     ^externalParts!
  5384.  
  5385. externalParts: collectionOfPartNames
  5386.     "Set my set of external parts. These are the parts that will be visible to the outside world after compiling me into a module."
  5387.  
  5388.     externalParts _ collectionOfPartNames.!
  5389.  
  5390. partIcon
  5391.     "Answer my part icon for the parts bin."
  5392.  
  5393.     ^partIcon!
  5394.  
  5395. partIcon: aForm
  5396.     "Set my part icon for the parts bin."
  5397.  
  5398.     partIcon _ aForm.!
  5399.  
  5400. prototype
  5401.     "Answer my prototype. This is the actual prototype, NOT a copy."
  5402.  
  5403.     (prototype isNil) ifTrue: [prototype _ self basicNew initialize].
  5404.     ^prototype!
  5405.  
  5406. useView
  5407.     "Answer class of the module Thing compiled from me or nil if I have never been compiled."
  5408.  
  5409.     ^useView!
  5410.  
  5411. useView: aClass
  5412.     "Set the class of the Thing that was compiled from me."
  5413.  
  5414.     useView _ aClass.! !
  5415.  
  5416. !Thing class methodsFor: 'private-initialize-destroy'!
  5417.  
  5418. aDefaultIcon
  5419.     "Answer one of the default icons at random."
  5420.  
  5421.     ^DefaultIcons at:
  5422.         ((Random new next * DefaultIcons size) truncated + 1)!
  5423.  
  5424. destroy
  5425.     "Eliminate any possibility of circular data structures and remove myself (a class) from the system."
  5426.  
  5427.     partIcon _ nil.
  5428.     explainText _ nil.
  5429.     partNamesAndIndices _ nil.
  5430.     externalParts _ nil.
  5431.     useView _ nil.
  5432.     prototype _ nil.
  5433.     self removeFromSystem.!
  5434.  
  5435. initializeBuiltThing
  5436.     "Initialize the class for a newly defined Thing."
  5437.  
  5438.     partIcon _ self aDefaultIcon deepCopy.
  5439.     explainText _ 'This Thing was constructed by the user.'.
  5440.     partNamesAndIndices _ OrderedCollection new.
  5441.     externalParts _ OrderedCollection new.
  5442.     useView _ nil.
  5443.     prototype _ self basicNew initialize.!
  5444.  
  5445. initializeByCopying: aThingClass
  5446.     "Initialize this Thing subclass by copying its fields from the given class. Used when creating an unencumbered class."
  5447.  
  5448.      partIcon _ aThingClass partIcon deepCopy.
  5449.     explainText _ aThingClass explainText deepCopy.
  5450.     partNamesAndIndices _ aThingClass partNamesAndIndices deepCopy.
  5451.     externalParts _ aThingClass externalParts deepCopy.
  5452.     useView _ nil.
  5453.     prototype _ nil.!
  5454.  
  5455. initializePartsList
  5456.     "Initialize the 'partsNamesAndIndices' class instance variable based on my instance variable names."
  5457.  
  5458.     | allInstVarNames |
  5459.     allInstVarNames _ self allInstVarNames.
  5460.     partNamesAndIndices _ OrderedCollection new: allInstVarNames size.
  5461.     (self instOffset + 1) to: allInstVarNames size do:
  5462.         [: i |
  5463.          partNamesAndIndices addLast:
  5464.             (Array
  5465.                 with: (allInstVarNames at: i) asSymbol
  5466.                 with: i)].!
  5467.  
  5468. initializePrimitive
  5469.     "Initialize the class for a primitive Thing."
  5470.  
  5471.     partIcon _ self aDefaultIcon.
  5472.     explainText _ 'This is a Primitive Thing.'.
  5473.     self initializePartsList.
  5474.     externalParts _ OrderedCollection new.
  5475.     useView _ nil.
  5476.     prototype _ self basicNew initialize.
  5477.     prototype
  5478.         initializeStructure;
  5479.         initializeValues;        "initialize values so constraints don't fail"
  5480.         initializeConstraints;
  5481.         initializeValues.        "reassert values after adding constraints"!
  5482.  
  5483. prototype: aThing
  5484.     "Private!! Register my prototype. Used by becomeUnencumberedClass."
  5485.  
  5486.     prototype _ aThing.!
  5487.  
  5488. successorName
  5489.     "Create a new, unique name for this class that is similar but not identical to the current name."
  5490.  
  5491.     | rs count str |
  5492.     rs _ ReadStream on: self name asString.
  5493.     rs setToEnd; skip: -1.
  5494.     [(rs position > 1) & (rs peek isDigit)]
  5495.         whileTrue: [rs skip: -1].
  5496.     ((rs position > 1) & (rs peek = $v))
  5497.         ifTrue: 
  5498.             [count _ rs position.
  5499.              rs reset.
  5500.              str _ rs next: count]
  5501.         ifFalse: [str _ rs contents].
  5502.     str _ str, 'v', ThingLabII uniqueNumber printString.
  5503.     ^str asSymbol!
  5504.  
  5505. vaporize
  5506.     "Delete this thing and its class."
  5507.     "Warning: Use with caution!!!!"
  5508.  
  5509.     prototype destroyAndRemoveClass.! !
  5510.  
  5511. !Thing class methodsFor: 'private-parts'!
  5512.  
  5513. instOffset
  5514.     "This is the number of internal (i.e. non-part) instance variables every Thing has. This offset must be added to change local inst var indices into indices for the object as a whole."
  5515.  
  5516.     ^3!
  5517.  
  5518. partNamesAndIndices
  5519.     "Answer a collection of (name, instVarIndex) pairs for my parts."
  5520.  
  5521.     ^partNamesAndIndices!
  5522.  
  5523. removeInstVarNamed: nameString 
  5524.     "Rename the instance the the given part to 'unusedNNN'."
  5525.  
  5526.     | instVars |
  5527.     instVars _ self instVarNames.
  5528.     1 to: instVars size do:
  5529.         [: i |
  5530.          (nameString = (instVars at: i)) ifTrue: 
  5531.             [^self
  5532.                 renameInstVarAt: i
  5533.                 as: 'unused', i printString]].
  5534.     self error: 'ThingLabII Internal Error -- could not find instVar with given name'.!
  5535.  
  5536. removePartNamed: partSymbol
  5537.     "Remove the part with the given name and its access methods."
  5538.  
  5539.     "remove the part as an instance variable and also remove its records in partNamesAndIndices and externalParts"
  5540.     self removeInstVarNamed: partSymbol asString.
  5541.     partNamesAndIndices _
  5542.         partNamesAndIndices select:
  5543.             [: entry | entry first ~= partSymbol].
  5544.     externalParts remove: partSymbol ifAbsent: [].
  5545.  
  5546.     "remove the get and put methods"
  5547.     self removeSelector: partSymbol.
  5548.     self removeSelector: ('prim', partSymbol, ':') asSymbol.!
  5549.  
  5550. renameInstVarAt: index as: nameString
  5551.     "Rename the instance variable with the given index in this class."
  5552.  
  5553.     self instVarNames at: index put: nameString.! !
  5554.  
  5555. !Thing class methodsFor: 'private-compiling'!
  5556.  
  5557. compileAccessMethodsFor: thingsOrObjects named: partNames
  5558.     "Compile access methods for the given parts. The two arguments should be sequenceable collections of the same size. thingsOrObjects are prototypes for the parts (either Things or normal Smalltalk objects) and partNames are the names for these parts."
  5559.  
  5560.     | encoder |
  5561.     encoder _ (Encoder new) init: self context: nil notifying: nil.
  5562.     partNames with: thingsOrObjects do:
  5563.         [: partName : thingOrObject |
  5564.          BusyCursor inc.
  5565.          self compileGetMethodFor: partName asString encoder: encoder.
  5566.          BusyCursor inc.
  5567.          thingOrObject isThing
  5568.             "ifTrue:
  5569.                 [self
  5570.                     compileThingPutMethodFor: partName asString
  5571.                     asA: thingOrObject
  5572.                     encoder: encoder]"
  5573.             ifFalse:
  5574.                 [self
  5575.                     compileNonThingPutMethodFor: partName asString
  5576.                     encoder: encoder]].!
  5577.  
  5578. compileGetMethodFor: partName encoder: anEncoder
  5579.     "Compile the get access method for the part with the given name. The method will take the form:
  5580.  
  5581.         XXX
  5582.             ^XXX"
  5583.  
  5584.     | selector returnNode block methodNode |
  5585.     selector _ partName asSymbol.
  5586.     returnNode _ ReturnNode new expr: (anEncoder encodeVariable: partName).
  5587.     block _ BlockNode new
  5588.         statements: (OrderedCollection with: returnNode)
  5589.         returns: true.
  5590.     methodNode _ MethodNode new
  5591.         selector: selector
  5592.         arguments: #()
  5593.         precedence: selector precedence
  5594.         temporaries: #()
  5595.         block: block
  5596.         encoder: anEncoder
  5597.         primitive: 0.
  5598.     self addSelector: selector withMethod: (methodNode generate).
  5599.     self organization classify: selector under: #access.!
  5600.  
  5601. compileNonThingPutMethodFor: partName encoder: anEncoder
  5602.     "Compile the put method for the part with the given name. The part is assumed to contain a normal Smalltalk object, not a Thing. The method will take the form:
  5603.  
  5604.         primXXX: arg
  5605.             XXX _ arg"
  5606.  
  5607.     | selector arg assignment block methodNode |
  5608.     selector _ ('prim', partName, ':') asSymbol.
  5609.     arg _ anEncoder autoBind: 'arg'.
  5610.     assignment _ AssignmentNode new
  5611.         variable: (anEncoder encodeVariable: partName)
  5612.         value: arg
  5613.         from: anEncoder.
  5614.     block _ BlockNode new
  5615.         statements: (OrderedCollection with: assignment)
  5616.         returns: false.
  5617.     block returnSelfIfNoOther.    "add '^self'"
  5618.     methodNode _ MethodNode new
  5619.         selector: selector
  5620.         arguments: (Array with: arg)
  5621.         precedence: selector precedence
  5622.         temporaries: #()
  5623.         block: block
  5624.         encoder: anEncoder
  5625.         primitive: 0.
  5626.     self addSelector: selector withMethod: methodNode generate.
  5627.     self organization classify: selector under: #access.!
  5628.  
  5629. compileThingPutMethodFor: partName asA: aThing encoder: anEncoder
  5630.     "Compile the put method for the part with the given name. The part is assumed to contain a Thing like the given example. The method will take the form:
  5631.  
  5632.         primXXX: arg
  5633.             XXX primYY: arg YY.
  5634.             XXX primZZ: arg ZZ"
  5635.  
  5636.     | selector arg rcvr statements s m1 block methodNode |
  5637.     selector _ ('prim', partName, ':') asSymbol.
  5638.     arg _ anEncoder autoBind: 'arg'.
  5639.     rcvr _ anEncoder encodeVariable: partName.
  5640.     statements _
  5641.         aThing class partNamesAndIndices collect: 
  5642.             [: entry | 
  5643.              s _ entry first asSymbol.
  5644.              m1 _ MessageNode new
  5645.                 receiver: arg
  5646.                 selector: s
  5647.                 arguments: #()
  5648.                 precedence: s precedence
  5649.                 from: anEncoder.
  5650.              s _ ('prim', entry first, ':') asSymbol.
  5651.              MessageNode new
  5652.                 receiver: rcvr
  5653.                 selector: s
  5654.                 arguments: (Array with: m1)
  5655.                 precedence: s precedence
  5656.                 from: anEncoder].
  5657.     block _ BlockNode new
  5658.         statements: statements
  5659.         returns: false.
  5660.     block returnSelfIfNoOther.    "add '^self'"
  5661.     methodNode _ MethodNode new
  5662.         selector: selector
  5663.         arguments: (Array with: arg)
  5664.         precedence: selector precedence
  5665.         temporaries: #()
  5666.         block: block
  5667.         encoder: anEncoder
  5668.         primitive: 0.
  5669.     self addSelector: selector withMethod: methodNode generate.
  5670.     self organization classify: selector under: #access.! !
  5671.  
  5672.  
  5673. Object subclass: #DeltaBluePlanner
  5674.     instanceVariableNames: ''
  5675.     classVariableNames: ''
  5676.     poolDictionaries: ''
  5677.     category: 'ThingLabII'!
  5678. DeltaBluePlanner comment:
  5679. 'I embody the DeltaBlue algorithm given in "The DeltaBlue Algorithm: An Incremental Constraint Hierarchy Solver" by Bjorn N. Freeman-Benson and John Maloney.
  5680. '!
  5681.  
  5682. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  5683.  
  5684. DeltaBluePlanner class
  5685.     instanceVariableNames: 'currentMark '!
  5686.  
  5687.  
  5688. !DeltaBluePlanner class methodsFor: 'add/remove'!
  5689.  
  5690. incrementalAdd: aConstraint
  5691.     "Entry point for adding a constraint. Add the given constraint and incrementally update the dataflow graph."
  5692.  
  5693.     (aConstraint isSatisfied) ifFalse:
  5694.         [self chooseNewMark.
  5695.          self privateAddConstraint: aConstraint].!
  5696.  
  5697. incrementalRemove: aConstraint
  5698.     "Entry point for removing a constraint. Remove the given constraint and incrementally update the dataflow graph."
  5699.  
  5700.     (aConstraint isSatisfied) ifTrue:
  5701.         [self chooseNewMark.
  5702.          self privateRemoveConstraint: aConstraint unmarkedOnly: false].! !
  5703.  
  5704. !DeltaBluePlanner class methodsFor: 'planning'!
  5705.  
  5706. extractPlanFromChangingThingDatas: thingDatas
  5707.     "Extract a plan for the constraints on the given set of changing (i.e. non-stay) thingDatas. If optimizeStays is true, it is assumed that all variables marked 'stay' were computed as the constraints were added. Since these variables will not change, they (and any variables upstream of them) will not be recomputed by the plan. If optimizeStays is false, all variables will be recomputed by the plan."
  5708.     "Two pass implementation:
  5709.       1. Build a plan potentially containing redundant constraints. Clear
  5710.          marks on all constraints as they are added to the plan.
  5711.       2. Filter out duplicate constraints by using marks."
  5712.  
  5713.     | plan todo i td c filteredPlan |
  5714.     plan _ Plan new: 1000.
  5715.     todo _ OrderedCollection new: 1000.
  5716.     thingDatas do:
  5717.         [: td |
  5718.          todo add: td.
  5719.          c _ td determinedBy.
  5720.          (c notNil) ifTrue:
  5721.              [(c shouldUseGiven: true) ifTrue:
  5722.                 [plan addLast: c.
  5723.                  c clearCommitted]]].
  5724.  
  5725.     [todo isEmpty] whileFalse:
  5726.         [td _ todo removeFirst.
  5727.          td usedBy do:
  5728.             [: c |
  5729.              (c shouldUseGiven: true) ifTrue:
  5730.                 [plan addLast: c.
  5731.                  c clearCommitted].
  5732.              c outDatasDo: [: out | todo add: out]]].
  5733.  
  5734.     filteredPlan _ Plan new: (plan size * 2) + 2.    "avoid growing"
  5735.     plan reverseDo:
  5736.         [: c |
  5737.          (c isCommitted not) ifTrue:
  5738.             [filteredPlan addFirst: c].
  5739.          c setCommitted].
  5740.     plan _ todo _ nil.
  5741.     ^filteredPlan!
  5742.  
  5743. extractPlanFromThing: aThing 
  5744.     "Extract the current solution for the given Thing's constraints as a Plan."
  5745.     "Details: There are two ways to extract a dataflow from the current DeltaBlue plan: top-down and bottom-up. Bottom-up starts with the terminal nodes and works 'upstream' in the dataflow graph. Top-down starts at all the source nodes and works down. This method implements bottom-up."
  5746.  
  5747.     | allThingDatas |
  5748.     allThingDatas _ IdentitySet new: 100.
  5749.     aThing allThingsDo:
  5750.         [: thing | allThingDatas addAll: thing thingDatas].
  5751.     ^self extractPlanFromThingDatas: allThingDatas optimizeStays: true!
  5752.  
  5753. extractPlanFromThingDatas: thingDatas optimizeStays: optimizeStays
  5754.     "Extract a plan for the constraints on the given set of thingDatas. If optimizeStays is true, it is assumed that all variables marked 'stay' were computed as the constraints were added. Since these variables will not change, they (and any variables upstream of them) will not be recomputed by the plan. If optimizeStays is false, all variables will be recomputed by the plan."
  5755.  
  5756.     | hotConstraints plan hotC |
  5757.     currentMark _ Time millisecondClockValue.
  5758.     hotConstraints _ OrderedCollection new: 200.
  5759.     plan _ Plan new: 100.
  5760.     thingDatas do:
  5761.         [: thingData |
  5762.          (thingData constraints size > 0) ifTrue:
  5763.              [(thingData determinedBy isNil) ifTrue:
  5764.                 [thingData mark: currentMark].
  5765.              thingData constraints do:
  5766.                 [: c |
  5767.                  (c isSatisfied)
  5768.                     ifTrue: [c clearCommitted]
  5769.                     ifFalse: [c setCommitted].
  5770.                  ((c isSatisfied) and:
  5771.                   [c inputsKnown: currentMark]) ifTrue:
  5772.                     [hotConstraints addFirst: c]]]].
  5773.  
  5774.     [hotConstraints isEmpty] whileFalse:
  5775.         [hotC _ hotConstraints removeFirst.
  5776.          ((hotC isCommitted not) and:
  5777.           [hotC inputsKnown: currentMark]) ifTrue:
  5778.             [(hotC shouldUseGiven: optimizeStays) ifTrue:
  5779.                 [plan addLast: hotC].
  5780.              hotC setCommitted.
  5781.              hotC outDatasDo:
  5782.                 [: out |
  5783.                  out mark: currentMark.
  5784.                  out usedBy do:
  5785.                     [: c |
  5786.                      (c isCommitted) ifFalse:
  5787.                         [hotConstraints addLast: c]]]]].
  5788.     ^plan! !
  5789.  
  5790. !DeltaBluePlanner class methodsFor: 'value propagation'!
  5791.  
  5792. propagateFrom: aThingData
  5793.     "The variable associated with the given ThingData has changed. Propagate new values downstream."
  5794.  
  5795.     | todo |
  5796.     (aThingData isNil) ifTrue: [^self].    "no constraints since ThingData is nil"
  5797.  
  5798.     todo _ OrderedCollection new: 100.
  5799.     todo add: aThingData.
  5800.     [todo isEmpty] whileFalse:
  5801.         [(todo removeFirst usedBy) do:
  5802.             [: constraint |
  5803.              constraint execute.
  5804.              constraint whichMethod
  5805.                 outDatasIn: constraint thingDatas
  5806.                 do: [: out | todo add: out]]].! !
  5807.  
  5808. !DeltaBluePlanner class methodsFor: 'private'!
  5809.  
  5810. addPropagateFrom: aConstraint execFlag: execFlag
  5811.     "Recompute the walkabout strengths and stay flags of all variables downstream of the given constraint. If execFlag is true, also recompute the actual values of all downstream variables whose stay flag is true. If the propagation succeeds without finding a cycle, answer true. If a cycle is detected, undo the propagation and answer false."
  5812.  
  5813.     | bindings thingDatas refs outs savedDBData i out cycleFound entry varIndex |
  5814.     "save output variable state to allow restoring"
  5815.     bindings _ aConstraint whichMethod bindings.
  5816.     thingDatas _ aConstraint thingDatas.
  5817.     refs _ aConstraint variables.
  5818.     outs _ OrderedCollection new: 12.
  5819.     savedDBData _ OrderedCollection new: 12.
  5820.     i _ bindings size.
  5821.     [i > 0] whileTrue:
  5822.         [((bindings at: i) == $o) ifTrue:
  5823.             [out _ thingDatas at: i.
  5824.              outs add: out.
  5825.              savedDBData add:
  5826.                 (Array
  5827.                     with: i
  5828.                     with: ((refs at: i) value)
  5829.                     with: out stay
  5830.                     with: out walkStrength)].
  5831.          i _ i - 1].
  5832.  
  5833.     "calculate and propagate new values"
  5834.     aConstraint calculateDeltaBlueData: execFlag.
  5835.     cycleFound _ self
  5836.         propagateFrom: outs
  5837.         watchFor: (aConstraint inDatas)
  5838.         execFlag: execFlag.
  5839.  
  5840.     "cycle found: must restore all values to their previous states"
  5841.     cycleFound ifTrue:
  5842.         [i _ savedDBData size.
  5843.          [i > 0] whileTrue:
  5844.             [entry _ savedDBData at: i.
  5845.              varIndex _ entry at: 1.
  5846.              out _ thingDatas at: varIndex.
  5847.              (refs at: varIndex) value: (entry at: 2).
  5848.              out stay: (entry at: 3).
  5849.              out walkStrength: (entry at: 4).
  5850.              i _ i - 1].
  5851.          self propagateFrom: outs watchFor: nil execFlag: execFlag].
  5852.  
  5853.     ^cycleFound not!
  5854.  
  5855. chooseNewMark
  5856.     "Select a new mark value."
  5857.  
  5858.     currentMark _ Time millisecondClockValue.
  5859.     (currentMark == 0) ifTrue: [currentMark _ 1].
  5860.         "zero always means unmarked"!
  5861.  
  5862. privateAddConstraint: aConstraint
  5863.     "Attempt to add the given constraint. If successful, resatisfy any overridden constraints. The markValue is not reset to avoid getting into an infinite loop alternately satisfying and unsatisfying a cycle of constaints."
  5864.  
  5865.     | overridden c |
  5866.     overridden _ OrderedCollection new: 50.
  5867.     self satisfy: aConstraint overriddenInto: overridden.
  5868.     [overridden isEmpty] whileFalse:
  5869.         [c _ overridden removeFirst.
  5870.          self satisfy: c overriddenInto: overridden].!
  5871.  
  5872. privateRemoveConstraint: aConstraint unmarkedOnly: unmarkedFlag
  5873.     "Remove the given constraint and incrementally update the dataflow graph."
  5874.  
  5875.     | outVars oldMark hotConstraints multiOutConstraints |
  5876.     "Take note of variables to propagate from. If this is part of a retract operation, we propagate only from the unmarked (downstream) outputs. Otherwise, we propagate from all outputs."
  5877.     outVars _ OrderedCollection new: 12.
  5878.     aConstraint outDatasDo:
  5879.         [: out |
  5880.          unmarkedFlag
  5881.             ifTrue:
  5882.                 [(out mark ~~ currentMark) ifTrue:
  5883.                     [outVars add: out]]
  5884.             ifFalse:
  5885.                 [outVars add: out]].
  5886.  
  5887.     "If this is a retract operation, choose a temporary mark, remembering the old one."
  5888.     unmarkedFlag ifTrue:
  5889.         [oldMark _ currentMark.
  5890.          self chooseNewMark].
  5891.  
  5892.     "NOTE: unsatisfy sets whichMethod to nil"
  5893.     aConstraint unsatisfy.
  5894.  
  5895.     "propagate DeltaBlue data and collect the affected constraints, sorted in order of decreasing strength"
  5896.     hotConstraints _ (SortedCollection new: 200)
  5897.         sortBlock: [: i : j | i isStrongerThan: j].
  5898.     multiOutConstraints _ OrderedCollection new: 100.
  5899.     self
  5900.         removePropagateFrom: outVars
  5901.         unsatisfiedInto: hotConstraints
  5902.         multiOutsInto: multiOutConstraints.
  5903.  
  5904.     "consider currently unsatisfied constraints for possible resatisfaction (except the one we are removing!!)"
  5905.     hotConstraints do:
  5906.         [: c |
  5907.          (c ~~ aConstraint) ifTrue:
  5908.             [self incrementalAdd: c]].
  5909.  
  5910.     "re-add constraints with multiple outputs"
  5911.     multiOutConstraints do:
  5912.         [: c |
  5913.          (c ~~ aConstraint) ifTrue:
  5914.             [c addToGraph.
  5915.              self incrementalAdd: c]].
  5916.  
  5917.     "restore old mark (which might have been messed up by re-adding constraints"
  5918.     unmarkedFlag ifTrue: [currentMark _ oldMark].!
  5919.  
  5920. propagateFrom: vars watchFor: cycleVars execFlag: execFlag
  5921.     "Recompute the walkabout strengths and stay flags of all variables downstream of the given variables. If execFlag is true, compute the values of variables whose stay flag is true. If cycleVars is not nil and any of the variables in cycleVars is encountered, stop and answer true. Otherwise, answer false."
  5922.  
  5923.     | todo outs i outVar |
  5924.     todo _ vars copy.
  5925.     [todo isEmpty] whileFalse:
  5926.         [(todo removeFirst usedBy) do:
  5927.             [: constraint |
  5928.              outs _ constraint calculateDeltaBlueData: execFlag.
  5929.              i _ outs size.
  5930.              [i > 0] whileTrue:
  5931.                 [outVar _ outs at: i.
  5932.                  ((cycleVars notNil) and:
  5933.                   [cycleVars includes: outVar]) ifTrue:
  5934.                     [^true    "cycle found"].
  5935.                  todo add: outVar.
  5936.                  i _ i - 1]]].
  5937.     ^false    "no cycle found"!
  5938.  
  5939. removePropagateFrom: vars unsatisfiedInto: hotConstraints multiOutsInto: multiOuts
  5940.     "Recompute the walkabout strengths and stay flags of all variables downstream of the given set of variables, collecting all unsatisfied downstream constraints into hotConstraints and all multiple output constraints into multiOuts."
  5941.  
  5942.     | todo var |
  5943.     todo _ OrderedCollection new: 100.
  5944.     vars do:
  5945.         [: var |
  5946.          var walkStrength: Strength absoluteWeakest.
  5947.          var stay: true.
  5948.          todo add: var].
  5949.  
  5950.     [todo isEmpty] whileFalse:
  5951.         [var _ todo removeFirst.
  5952.          var constraints do:
  5953.             [: c |
  5954.              (c isSatisfied) ifFalse:
  5955.                 [hotConstraints add: c]].
  5956.          var usedBy do:
  5957.             [: c |
  5958.              (c hasMultipleOutputs)
  5959.                 ifTrue:
  5960.                     [self incrementalRemove: c.
  5961.                      c removeFromGraph.
  5962.                      multiOuts add: c]
  5963.                 ifFalse:
  5964.                     [todo add: ((c calculateDeltaBlueData: false) at: 1)]]].!
  5965.  
  5966. retract: aConstraint
  5967.     "Retract the given constraint because it is being overridden by another constraint. If the constraint has only one output, no recomputation of DeltaBlue information is necessary and it can simply be unsatisfied. If the constraint has more than one output, retracting it is more expensive as we must resatisfying constraints downstream of its unmarked outputs. This is necessary because before the constraint can be reconsidered for satisfaction we must know the walkabout strengths of its variables in its absence."
  5968.  
  5969.     | method |
  5970.     method _ aConstraint whichMethod.
  5971.     (method isNil) ifTrue: [^self].    "constraint is already retracted"
  5972.     ((aConstraint hasMultipleOutputs) and:
  5973.      [(method bindings select: [: b | b == $o]) size > 1])
  5974.         ifTrue:    "retracting is expensive if there's more than one output"
  5975.             [self privateRemoveConstraint: aConstraint unmarkedOnly: true]
  5976.         ifFalse:    "otherwise, retracting is cheap"
  5977.             [aConstraint unsatisfy].!
  5978.  
  5979. satisfy: aConstraint overriddenInto: overridden
  5980.     "Attempt to find a method to satisfy the given constraint without creating a cycle. If successful, add the constraint and put all overridden constraints in the given collection."
  5981.  
  5982.     | methods foundMethod bindings thingDatas i td oldC |
  5983.     (aConstraint isSatisfied) ifTrue: [^self].        "already satisfied"
  5984.  
  5985.     methods _ aConstraint selectMethodsGiven: currentMark.
  5986.     foundMethod _ false.
  5987.     [methods isEmpty | foundMethod] whileFalse:
  5988.         [aConstraint whichMethod: (methods removeFirst).
  5989.          foundMethod _
  5990.             self addPropagateFrom: aConstraint execFlag: true].
  5991.  
  5992.     foundMethod
  5993.         ifTrue:
  5994.             ["constraint satisfaction succeeded"
  5995.              bindings _ aConstraint whichMethod bindings.
  5996.              thingDatas _ aConstraint thingDatas.
  5997.              i _ bindings size.
  5998.              [i > 0] whileTrue:
  5999.                 [td _ thingDatas at: i.
  6000.                  ((bindings at: i) == $i) ifTrue:
  6001.                     [td addUsedBy: aConstraint].
  6002.                  ((bindings at: i) == $o) ifTrue:
  6003.                     [td mark: currentMark.
  6004.                      oldC _ td determinedBy.
  6005.                      (oldC notNil) ifTrue:
  6006.                          [overridden add: oldC.
  6007.                          self retract: oldC].
  6008.                      td determinedBy: aConstraint].
  6009.                  i _ i - 1]]
  6010.         ifFalse:
  6011.             ["constraint satisfaction failed"
  6012.              aConstraint whichMethod: nil.
  6013.              (aConstraint isRequired) ifTrue:
  6014.                 [self notify:
  6015.                   ('Could not find a way to satisfy a required constraint.\',
  6016.                    'The constraint will be left unsatisfied. Please proceed.')
  6017.                     withCRs]].! !
  6018.  
  6019. Object subclass: #DebugConstraintRecord
  6020.     instanceVariableNames: 'constraint glyph varGlyphs solutions '
  6021.     classVariableNames: ''
  6022.     poolDictionaries: ''
  6023.     category: 'ThingLabII-UI-Debugger'!
  6024. DebugConstraintRecord comment:
  6025. 'Each partition of the constraint graph being debugged contains a collection of three-tuples (DebugConstraintRecords) of the form:
  6026.  
  6027.     constraint        -- the actual constraint object <Constraint>
  6028.     glyph             -- a glyph for the constraint <ConstraintGlyph>
  6029.     solutions            -- a collection of constraint methods, one per solution {Method}
  6030.  
  6031. Each tuple in a partition has the same number of solutions. The i-th solution for a partition is found by taking the i-th element of each tuple''s solutions collection. The first solution is always the current solution. The remaining solutions are the possible solutions. (The current solution should be among them unless there is a bug in the constraint solver!!).
  6032. '!
  6033.  
  6034.  
  6035. !DebugConstraintRecord methodsFor: 'accessing'!
  6036.  
  6037. constraint
  6038.  
  6039.     ^constraint!
  6040.  
  6041. constraint: aConstraint
  6042.  
  6043.     constraint _ aConstraint.!
  6044.  
  6045. glyph
  6046.  
  6047.     ^glyph!
  6048.  
  6049. glyph: aConstraintGlyph
  6050.  
  6051.     glyph _ aConstraintGlyph.!
  6052.  
  6053. solutions
  6054.  
  6055.     ^solutions!
  6056.  
  6057. solutions: aCollectionOfMethods
  6058.  
  6059.     solutions_ aCollectionOfMethods.!
  6060.  
  6061. varGlyphs
  6062.  
  6063.     ^varGlyphs!
  6064.  
  6065. varGlyphs: aCollectionOfVariableGlyphs
  6066.  
  6067.     varGlyphs _ aCollectionOfVariableGlyphs.! !
  6068.  
  6069. !DebugConstraintRecord methodsFor: 'operations'!
  6070.  
  6071. centerConstraint: graphCenter
  6072.     "Place my constraint glyph at the center of its operands. If the constraint has only one operand, place it on the side of the operand farthest from the center of the graph."
  6073.  
  6074.     | sum outVec |
  6075.     (varGlyphs size = 1)
  6076.         ifTrue:
  6077.             [outVec _ ((varGlyphs at: 1) location - graphCenter) unitVector.
  6078.              glyph location: varGlyphs first location + (outVec * 35.0) rounded]
  6079.         ifFalse:
  6080.              [sum _ varGlyphs
  6081.                         inject: 0@0
  6082.                         into: [: sum : varGlyph | sum + varGlyph location].
  6083.              glyph location: sum // varGlyphs size].!
  6084.  
  6085. updateCurrentSolution
  6086.     "Update the current solution for my constraint."
  6087.  
  6088.     solutions at: 1 put: constraint whichMethod.!
  6089.  
  6090. updateGlyph: solutionIndex
  6091.     "Update the constraint glyph for the given solution."
  6092.  
  6093.     | method inVars outVars unusedVars |
  6094.     method _ solutions at: solutionIndex.
  6095.     (method isNil)
  6096.         ifTrue: [glyph ins: #() outs: #() unused: varGlyphs]
  6097.         ifFalse:
  6098.             [inVars _ OrderedCollection new.
  6099.              outVars _ OrderedCollection new.
  6100.              unusedVars _ varGlyphs asOrderedCollection.
  6101.              varGlyphs with: method bindings do:
  6102.                 [: var : binding |
  6103.                  (binding == $i) ifTrue:
  6104.                     [inVars add: var. unusedVars remove: var].
  6105.                  (binding == $o) ifTrue:
  6106.                     [outVars add: var. unusedVars remove: var]].
  6107.             glyph ins: inVars outs: outVars unused: unusedVars].! !
  6108.  
  6109. Object subclass: #ModuleVarTableEntry
  6110.     instanceVariableNames: 'thingData name type reference value tempFlag constFlag constAncestors '
  6111.     classVariableNames: ''
  6112.     poolDictionaries: ''
  6113.     category: 'ThingLabII-Module Compiler'!
  6114. ModuleVarTableEntry comment:
  6115. 'I am used to represent a constrained variable during Module compilation. As analysis proceeds, I am classified as one of:
  6116.     external        -- part of an external part
  6117.     internal        -- a non-external variable
  6118.     temporary    -- an internal variable than does not hold
  6119.                     state between constraint satisfaction passes
  6120.     constant        -- an internal variable whose value is constant
  6121.  
  6122. Temporary and constant variables do not require space in the finished module.'!
  6123.  
  6124.  
  6125. !ModuleVarTableEntry methodsFor: 'initialize-release'!
  6126.  
  6127. on: aReference
  6128.     "Initialize a new variable table entry for the given Reference."
  6129.  
  6130.     thingData _ aReference thingData.
  6131.     name _ 'v', thingData asOop printString.
  6132.     type _ #internal.            "assume internal until declared external"
  6133.     reference _ aReference.
  6134.     value _ aReference value.
  6135.  
  6136.     "the following are used only during variable use analysis:"
  6137.     tempFlag _ true.            "assume temporary until shown otherwise"
  6138.     constFlag _ true.            "assume constant until shown otherwise"
  6139.     constAncestors _ nil.        "used to detect constants"! !
  6140.  
  6141. !ModuleVarTableEntry methodsFor: 'access'!
  6142.  
  6143. name
  6144.  
  6145.     ^name!
  6146.  
  6147. name: aName
  6148.  
  6149.     name _ aName.!
  6150.  
  6151. reference
  6152.     "Anwer my reference."
  6153.  
  6154.     ^reference!
  6155.  
  6156. thingData
  6157.  
  6158.     ^thingData!
  6159.  
  6160. value
  6161.  
  6162.     ^value! !
  6163.  
  6164. !ModuleVarTableEntry methodsFor: 'operations'!
  6165.  
  6166. classify
  6167.     "Decide the type of this variable. This method assumes that we have already recorded the status of this variable for all possible solutions. A variable may be:
  6168.         #external -- an external part
  6169.         #virtual -- a virtual, external part (#virtual implies #external)
  6170.         #internal -- invisible but holds state
  6171.         #temporary -- does NOT hold state state
  6172.         #constant -- stay flag is true for every flow, with the same ancestors"
  6173.  
  6174.     (self isExternal not) ifTrue:
  6175.         [constFlag & ((value isKindOf: Number) | (value isMemberOf: String))
  6176.             ifTrue: [type _ #constant]
  6177.             ifFalse: [tempFlag ifTrue: [type _ #temporary]]].
  6178.     constFlag _ constAncestors _ nil.
  6179.     tempFlag _ nil.
  6180.  
  6181.     "Note: non-external, non-constant, non-temporary variables are #internal"!
  6182.  
  6183. makeExternal: aReference
  6184.     "Make this an external variable for the part with the given top-level reference."
  6185.  
  6186.     type _ #external.
  6187.     reference _ aReference.
  6188.     tempFlag _ nil.         "not relevant for external variables"
  6189.     constFlag _ nil.        "ditto"
  6190.     constAncestors _ nil.    "ditto"!
  6191.  
  6192. makeVirtual
  6193.     "Make this entry be a virtual external variable."
  6194.  
  6195.     (self isExternal) ifFalse:
  6196.         [self error: 'Only external variables may be virtual parts!!'].
  6197.     type _ #virtual.!
  6198.  
  6199. recordCurrentStatus
  6200.     "Record the status of this variable in the current solution. This information will later be used to classify the variable; see 'classify' for further details."
  6201.  
  6202.     (self isExternal not) ifTrue:
  6203.         [constFlag ifTrue:
  6204.             [((thingData stay) and:
  6205.               [self sameAncestors: thingData ancestors]) ifFalse:
  6206.                 [constFlag _ false]].
  6207.          tempFlag ifTrue:
  6208.             [((thingData determinedBy notNil) and:
  6209.                [thingData usedBy isEmpty not]) ifFalse:
  6210.                 [tempFlag _ false]]].! !
  6211.  
  6212. !ModuleVarTableEntry methodsFor: 'queries'!
  6213.  
  6214. isConstant
  6215.     "Answer true if I am a constant in all solutions."
  6216.  
  6217.     ^type == #constant!
  6218.  
  6219. isExternal
  6220.     "Answer true if I am an external part. (Note: #virtual implies #external)."
  6221.  
  6222.     ^(type == #external) | (type == #virtual)!
  6223.  
  6224. isInternal
  6225.     "Answer true if I am an internal part."
  6226.  
  6227.     ^type == #internal!
  6228.  
  6229. isOutput
  6230.     "Answer true if I am an external output variable in the current solution."
  6231.  
  6232.     ^(self isExternal) and:
  6233.       [thingData determinedBy notNil]!
  6234.  
  6235. isTemporary
  6236.     "Answer true if I am used as a temporary in all solutions."
  6237.  
  6238.     ^type == #temporary!
  6239.  
  6240. isVirtual
  6241.     "Answer true if I am a virtual external part."
  6242.  
  6243.     ^type == #virtual! !
  6244.  
  6245. !ModuleVarTableEntry methodsFor: 'code generation'!
  6246.  
  6247. getCodeStringOn: aStream
  6248.     "Append to the given stream a code string to get the value of my variable."
  6249.  
  6250.     (self isExternal) ifTrue:
  6251.         [(reference fullPath) do:
  6252.             [: part | aStream nextPutAll: part; space].
  6253.          aStream skip: -1].
  6254.     (self isConstant) ifTrue: [^value storeOn: aStream].
  6255.     (self isInternal | self isTemporary) ifTrue: [^name].!
  6256.  
  6257. literalTreeForUsing: anEncoder
  6258.     "I am a constant. Use the given encoder to build and answer a parse tree for my value's storeString."
  6259.  
  6260.     | tree |
  6261.     (self isConstant) ifFalse: [self error: 'Module Compiler Error'].
  6262.     tree _ EquationParser
  6263.         parse: ('Doit ', value storeString) readStream
  6264.         withEncoder: anEncoder.
  6265.     ^tree block statements first!
  6266.  
  6267. putCodeStringOn: aStream
  6268.     "Append to the given stream a code string to set the value of my variable."
  6269.  
  6270.     (self isExternal) ifTrue:
  6271.         [(reference finalVarPath) do:
  6272.             [: part | aStream nextPutAll: part; space].
  6273.          aStream nextPutAll: 'prim'.
  6274.          aStream nextPutAll: reference part.
  6275.          aStream nextPutAll: ': '].
  6276.     (self isInternal | self isTemporary) ifTrue: [aStream nextPutAll: name, ' _ '].
  6277.     (self isConstant) ifTrue:
  6278.         ["can't change a constant; we must have mis-categorized this variable"
  6279.          self error: 'ThingLabII Implementation Error'].!
  6280.  
  6281. strengthCodeStringOn: aStream
  6282.     "Append to the given stream a code string to get the walkabout strength for my variable."
  6283.  
  6284.     (self isExternal)
  6285.         ifTrue:
  6286.             [aStream nextPut: $(.
  6287.              (reference finalVarPath) do:
  6288.                 [: part | aStream nextPutAll: part; space].
  6289.              aStream nextPutAll: 'strengthFor: #'.
  6290.              aStream nextPutAll: reference part.
  6291.              aStream nextPut: $).
  6292.              ^aStream contents]
  6293.     ifFalse:
  6294.         [self error: 'ThingLabII Implementation Error'].!
  6295.  
  6296. thingDataCodeStringOn: aStream
  6297.     "Append to the given stream a code string to get the ThingData for my variable."
  6298.  
  6299.     (self isExternal)
  6300.         ifTrue:
  6301.             [aStream nextPut: $(.
  6302.              (reference finalVarPath) do:
  6303.                 [: part | aStream nextPutAll: part; space].
  6304.              aStream nextPutAll: 'thingDataFor: #'.
  6305.              aStream nextPutAll: reference part.
  6306.              aStream nextPut: $).
  6307.              ^aStream contents]
  6308.     ifFalse:
  6309.         [self error: 'ThingLabII Implementation Error'].! !
  6310.  
  6311. !ModuleVarTableEntry methodsFor: 'printing'!
  6312.  
  6313. printOn: aStream
  6314.  
  6315.     aStream nextPutAll: name.! !
  6316.  
  6317. !ModuleVarTableEntry methodsFor: 'private'!
  6318.  
  6319. sameAncestors: ancestors
  6320.     "If no ancestors are currently recorded for me, remember this set and answer true. Otherwise, compare the previously recorded ancestors to the given set of ancestors and return true iff they are the same."
  6321.  
  6322.     (constAncestors isNil)
  6323.         ifTrue:
  6324.             [constAncestors _ ancestors.
  6325.              ^true]
  6326.         ifFalse:
  6327.             [^self set: constAncestors equals: ancestors].!
  6328.  
  6329. set: setA equals: setB
  6330.     "Answer true if setA contains exactly the same elements as setB."
  6331.  
  6332.     (setA size ~= setB size) ifTrue: [^false].
  6333.     setA do: [: elementA | (setB includes: elementA) ifFalse: [^false]].
  6334.     setB do: [: elementB | (setA includes: elementB) ifFalse: [^false]].
  6335.     ^true! !
  6336. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  6337.  
  6338. ModuleVarTableEntry class
  6339.     instanceVariableNames: ''!
  6340.  
  6341.  
  6342. !ModuleVarTableEntry class methodsFor: 'instance creation'!
  6343.  
  6344. on: aReference
  6345.     "Create a new instance of me for the referenced variable."
  6346.  
  6347.     ^(super new) on: aReference! !
  6348.  
  6349. Object subclass: #ThingPerf
  6350.     instanceVariableNames: 'partsList thing '
  6351.     classVariableNames: ''
  6352.     poolDictionaries: ''
  6353.     category: 'ThingLabII-Things-Support'!
  6354.  
  6355.  
  6356. !ThingPerf methodsFor: 'public'!
  6357.  
  6358. doTests: n
  6359.     "Do performance tests, printing the results in the Transcript."
  6360.     "ThingPerf new doTests: 10"
  6361.  
  6362.     | t editConstraint plan bluePlanner |
  6363.     t _ Time millisecondsToRun: [self buildThing: n].
  6364.     self report: ('Building ', n printString, ' node Thing: ') time: t.
  6365.  
  6366.     t _ Time millisecondsToRun: [self addConstraints].
  6367.     self report: 'Adding Equality Constraints: ' time: t.
  6368.  
  6369.     editConstraint _
  6370.         EditConstraint
  6371.             ref: thing->#n1.value
  6372.             strength: #preferred.
  6373.     "warm up Reference caches"
  6374.     editConstraint addConstraint; removeConstraint.
  6375.  
  6376.     t _ Time millisecondsToRun: [editConstraint addConstraint].
  6377.     self report: 'Add constraint (case 1): ' time: t.
  6378.     t _ Time millisecondsToRun: [thing set: #n1.value to: 1 strength: #preferred].
  6379.     self report: 'Setting first node: (case 1a): ' time: t.
  6380.     t _ Time millisecondsToRun:
  6381.         [thing
  6382.             set: ('n', n printString, '.value') asSymbol
  6383.             to: 1 strength: #preferred].
  6384.     self report: 'Setting last node: (case 1b): ' time: t.
  6385.     t _ Time millisecondsToRun:
  6386.         [plan _ DeltaBluePlanner extractPlanFromThing: thing].
  6387.     self report: 'Make Plan (case 1): ' time: t.
  6388.     t _ Time millisecondsToRun: [plan execute].
  6389.     self report: 'Execute Plan (case 1): ' time: t.
  6390.     t _ Time millisecondsToRun:
  6391.         [bluePlanner _ BluePlanner new on: thing].
  6392.     self report: 'Make Blue Planner (case 1): ' time: t.
  6393.     t _ Time millisecondsToRun:
  6394.         [plan _ bluePlanner plan].
  6395.     self report: 'Blue Planning Time (case 1): ' time: t.
  6396.     t _ Time millisecondsToRun: [editConstraint removeConstraint].
  6397.     self report: 'Remove constraint (case 1): ' time: t.
  6398.     editConstraint destroy.
  6399.  
  6400.     editConstraint _
  6401.         EditConstraint
  6402.             ref: thing->#n1.value
  6403.             strength: #weakDefault.
  6404.     "warm up Reference caches"
  6405.     editConstraint addConstraint; removeConstraint.
  6406.     Transcript cr.
  6407.  
  6408.     t _ Time millisecondsToRun: [editConstraint addConstraint].
  6409.     self report: 'Add constraint (case 2): ' time: t.
  6410.     t _ Time millisecondsToRun: [thing set: #n1.value to: 1 strength: #weakDefault].
  6411.     self report: 'Setting first node: (case 2a): ' time: t.
  6412.     t _ Time millisecondsToRun:
  6413.         [thing
  6414.             set: ('n', n printString, '.value') asSymbol
  6415.             to: 1 strength: #weakDefault].
  6416.     self report: 'Setting last node: (case 2b): ' time: t.
  6417.     t _ Time millisecondsToRun:
  6418.         [plan _ DeltaBluePlanner extractPlanFromThing: thing].
  6419.     self report: 'Make Plan (case 2): ' time: t.
  6420.     t _ Time millisecondsToRun: [plan execute].
  6421.     self report: 'Execute Plan (case 2): ' time: t.
  6422.     t _ Time millisecondsToRun:
  6423.         [bluePlanner _ BluePlanner new on: thing].
  6424.     self report: 'Make Blue Planner (case 2): ' time: t.
  6425.     t _ Time millisecondsToRun:
  6426.         [plan _ bluePlanner plan].
  6427.     self report: 'Blue Planning Time (case 2): ' time: t.
  6428.     t _ Time millisecondsToRun: [editConstraint removeConstraint].
  6429.     self report: 'Remove constraint (case 2): ' time: t.
  6430.     editConstraint destroy.
  6431.  
  6432.     t _ Time millisecondsToRun: [thing destroyAndRemoveClass].
  6433.     self report: 'Destroying Thing: ' time: t.
  6434.     Transcript cr.! !
  6435.  
  6436. !ThingPerf methodsFor: 'private'!
  6437.  
  6438. addConstraints
  6439.  
  6440.     | p1 p2 |
  6441.     1 to: (partsList size - 1) do:
  6442.         [: i |
  6443.          p1 _ (partsList at: i), '.value'.
  6444.          p2 _ (partsList at: i + 1), '.value'.
  6445.          thing require: p1 equals: p2].
  6446.     thing defaultStay: (partsList last, '.value').!
  6447.  
  6448. buildThing: numberOfNodes
  6449.  
  6450.     partsList _ (1 to: numberOfNodes) collect:
  6451.         [: i | ('n', i printString) asSymbol].
  6452.     thing _ Thing defineNewThingNamed: #PerfTestThing.
  6453.     thing
  6454.         addPartsNamed: partsList
  6455.         toHold: ((1 to: numberOfNodes) collect: [: i | Node new]).!
  6456.  
  6457. partitionTest: numberOfNodes
  6458.     "Measure performance of the partitioning algorithm."
  6459.     "ThingPerf new partitionTest: 10"
  6460.  
  6461.     | t partitions |
  6462.     t _ Time millisecondsToRun: [self buildThing: numberOfNodes].
  6463.     self report: ('Building ', numberOfNodes printString, ' node Thing: ') time: t.
  6464.  
  6465.     t _ Time millisecondsToRun: [self addConstraints].
  6466.     self report: 'Adding Equality Constraints: ' time: t.
  6467.  
  6468.     t _ Time millisecondsToRun: [partitions _ Partitioner partition: thing].
  6469.  
  6470.     self report: 'Partitioning took: ' time: t.
  6471.     Transcript show: 'Partitions: ', (partitions collect: [: p | p size]) printString.
  6472.     Transcript cr; cr.
  6473.  
  6474.     t _ Time millisecondsToRun: [thing destroyAndRemoveClass].
  6475.     self report: 'Destroying Thing: ' time: t.!
  6476.  
  6477. report: string time: time
  6478.  
  6479.     Transcript show: string, time printString, ' milliseconds'; cr.! !
  6480.  
  6481. Encoder subclass: #EquationEncoder
  6482.     instanceVariableNames: ''
  6483.     classVariableNames: ''
  6484.     poolDictionaries: ''
  6485.     category: 'ThingLabII-Equations'!
  6486.  
  6487.  
  6488. !EquationEncoder methodsFor: 'encoding'!
  6489.  
  6490. encodeVariable: name
  6491.     "If the given variable is not already in my scopeTable, just make it a new temp."
  6492.  
  6493.     ^scopeTable
  6494.         at: name
  6495.         ifAbsent: 
  6496.             [self lookupInPools: name 
  6497.                  ifFound: [: assoc | ^self global: assoc name: name].
  6498.              ^self reallyBindTemp: name]! !
  6499.  
  6500. View subclass: #ModuleCompilerView
  6501.     instanceVariableNames: 'state '
  6502.     classVariableNames: 'BlackAndWhites Icons Locations '
  6503.     poolDictionaries: ''
  6504.     category: 'ThingLabII-Module Compiler'!
  6505.  
  6506.  
  6507. !ModuleCompilerView methodsFor: 'state control'!
  6508.  
  6509. incrementState
  6510.  
  6511.     state _ state + 1.
  6512.     self displayView.!
  6513.  
  6514. initializeState
  6515.  
  6516.     state _ 1.
  6517.     self borderWidth: 0.
  6518.     self insideColor: nil.! !
  6519.  
  6520. !ModuleCompilerView methodsFor: 'displaying'!
  6521.  
  6522. displayView
  6523.  
  6524.     | displayBox tempForm colors |
  6525.     displayBox _ self insetDisplayBox.
  6526.     tempForm _ Form extent: displayBox extent.
  6527.     colors _ BlackAndWhites at: state.
  6528.     colors with: Locations do:
  6529.         [: color : loc | 
  6530.          (Icons at: (loc at: 1))
  6531.             displayOn: tempForm
  6532.             at: ((loc at: 2)@(loc at: 3))
  6533.             clippingBox: (tempForm boundingBox)
  6534.             rule: (Form paint)
  6535.             mask: (Form perform: color)].
  6536.     tempForm displayOn: Display at: displayBox topLeft.! !
  6537.  
  6538. !ModuleCompilerView methodsFor: 'termination'!
  6539.  
  6540. closeAndRemove
  6541.  
  6542.     self topView controller close.
  6543.     ScheduledControllers unschedule: self topView controller.
  6544.     ScheduledControllers activeController flushDisplayBits.
  6545.     ScheduledControllers activeController view display.! !
  6546. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  6547.  
  6548. ModuleCompilerView class
  6549.     instanceVariableNames: ''!
  6550.  
  6551.  
  6552. !ModuleCompilerView class methodsFor: 'class initialization'!
  6553.  
  6554. initialize
  6555.     "ModuleCompilerView initialize"
  6556.  
  6557.     self initializeBlackAndWhites.
  6558.     self initializeLocations.
  6559.     self initializeIcons.!
  6560.  
  6561. initializeBlackAndWhites
  6562.  
  6563.     BlackAndWhites _ #(
  6564.         (black black white white gray gray white gray white white gray gray)
  6565.         (black black black white black gray white gray white white gray gray)
  6566.         (black black black black black black white gray white white gray gray)
  6567.         (black black black black black black black black white white gray gray)
  6568.         (black black black black black black black black black white black gray)
  6569.         (black black black black black black black black black black black black)).!
  6570.  
  6571. initializeIcons
  6572.  
  6573.     Icons _ Dictionary new.
  6574.     Icons at: #allVars put: (Form
  6575.         extent: 47@54
  6576.         fromArray: #(0 0 0 0 0 0 16383 65535 65528 16383 65535 65528 12288 0 24 12288 0 24 12288 0 24 12799 65535 65304 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12799 65535 65304 12288 0 24 12288 0 24 12799 65535 65304 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12799 65535 65304 12288 0 24 12288 0 24 12799 65535 65304 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12544 0 280 12799 65535 65304 12288 0 24 12288 0 24 12288 0 24 16383 65535 65528 16383 65535 65528 0 0 0 0 0 0)
  6577.         offset: 0@0).
  6578.     Icons at: #someVars put: (Form
  6579.         extent: 45@52
  6580.         fromArray: #(0 0 0 32767 65535 65520 32767 65535 65520 24576 0 48 24576 0 48 24576 0 48 25599 65535 65072 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25599 65535 65072 24576 0 48 24576 0 48 25599 65535 65072 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25599 65535 65072 24576 0 48 24576 0 48 25599 65535 65072 25429 21845 22064 25258 43690 43568 25429 21845 22064 25258 43690 43568 25429 21845 22064 25258 43690 43568 25429 21845 22064 25258 43690 43568 25429 21845 22064 25258 43690 43568 25599 65535 65072 24576 0 48 24576 0 48 24576 0 48 32767 65535 65520 32767 65535 65520 0 0 0)
  6581.         offset: 0@0).
  6582.     Icons at: #fewVars put: (Form
  6583.         extent: 45@38
  6584.         fromArray: #(0 0 0 32767 65535 65520 32767 65535 65520 24576 0 48 24576 0 48 24576 0 48 25599 65535 65072 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25599 65535 65072 24576 0 48 24576 0 48 25599 65535 65072 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25599 65535 65072 24576 0 48 24576 0 48 24576 0 48 32767 65535 65520 32767 65535 65520 0 0 0)
  6585.         offset: 0@0).
  6586.     Icons at: #allCons put: (Form
  6587.         extent: 51@55
  6588.         fromArray: #(0 0 0 0 0 0 0 0 0 7 49152 0 0 24 12288 0 0 48 6144 0 0 32 2048 0 0 64 1024 0 248 64 1024 0 774 192 1024 0 1539 832 1024 0 1025 1088 1024 0 2048 38944 2048 0 2048 41008 6144 0 2048 49176 12288 0 2048 32783 49152 0 2048 32776 8192 0 1025 16 8192 0 1539 16 4096 0 774 16 2048 0 248 16 2048 0 16 32 1272 0 16 32 1798 0 16 32 1539 0 8 112 1025 0 8 142 2048 32768 8 257 51200 32768 4 512 14336 32768 4 1024 2048 32768 31 2048 2048 32768 96 61440 1025 0 192 24576 1539 0 128 8192 1798 0 256 4096 2296 0 256 4096 2048 0 256 4096 4096 0 256 4096 4096 0 256 4096 4096 0 128 8192 8192 0 192 24576 8192 0 96 49152 16384 0 31 1 61440 0 0 6 3072 0 0 12 1536 0 0 8 512 0 0 16 256 0 0 16 256 0 0 16 256 0 0 16 256 0 0 16 256 0 0 8 512 0 0 12 1536 0 0 6 3072 0 0 1 61440 0 0 0 0 0 0 0 0 0)
  6589.         offset: 0@0).
  6590.     Icons at: #someCons put: (Form
  6591.         extent: 50@54
  6592.         fromArray: #(0 0 0 0 0 15 32768 0 0 48 24576 0 0 96 12288 0 0 64 4096 0 0 128 2048 0 496 128 2048 0 1548 384 2048 0 3078 1664 2048 0 2050 2176 2048 0 4097 12352 4096 0 4097 16480 12288 0 4097 32816 24576 0 4097 31 32768 0 4097 16 16384 0 2050 32 16384 0 3078 32 8192 0 1548 32 4096 0 496 32 4096 0 32 64 2544 0 32 64 3596 0 32 64 3078 0 16 224 2050 0 16 284 4097 0 16 515 36865 0 8 1024 28673 0 8 2048 4097 0 62 4096 4097 0 213 57344 2050 0 426 49152 3078 0 341 16384 3596 0 682 40960 4592 0 853 24576 4096 0 682 40960 8192 0 853 24576 8192 0 682 40960 8192 0 341 16384 16384 0 426 49152 16384 0 213 32768 32768 0 62 3 57344 0 0 13 22528 0 0 26 44032 0 0 21 21504 0 0 42 43520 0 0 53 22016 0 0 42 43520 0 0 53 22016 0 0 42 43520 0 0 21 21504 0 0 26 44032 0 0 13 22528 0 0 3 57344 0 0 0 0 0 0 0 0 0)
  6593.         offset: 0@0).
  6594.     Icons at: #fewCons put: (Form
  6595.         extent: 49@34
  6596.         fromArray: #(0 0 0 0 0 31 0 0 0 96 49152 0 0 192 24576 0 0 128 8192 0 0 256 4096 0 992 256 4096 0 3096 768 4096 0 6156 3328 4096 0 4100 4352 4096 0 8194 24704 8192 0 8194 32960 24576 0 8195 96 49152 0 8194 31 0 0 8194 0 32768 0 4100 0 32768 0 6156 0 16384 0 3088 0 8192 0 992 0 8192 0 0 0 5088 0 0 0 7192 0 0 0 6156 0 0 0 4100 0 0 0 8194 0 0 0 8194 0 0 0 8194 0 0 0 8194 0 0 0 8194 0 0 0 4100 0 0 0 6156 0 0 0 3096 0 0 0 992 0 0 0 0 0 0 0 0 0)
  6597.         offset: 0@0).
  6598.     Icons at: #optimize put: (Form
  6599.         extent: 45@52
  6600.         fromArray: #(0 0 0 32767 65535 65520 32767 65535 65520 24576 0 48 24576 0 48 24576 0 48 25599 65535 65072 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25599 65535 65072 24576 0 48 24576 0 48 25599 65535 65072 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25088 0 560 25592 0 32304 25599 65535 65072 25086 1 64560 25087 7 64560 25599 65535 65072 25439 62847 63024 25263 64255 59952 25431 65535 22064 25259 65534 43568 25429 32765 22064 25258 65530 43568 25429 65533 22064 25259 65535 43568 25439 65023 54832 25279 64255 59952 25599 65535 65072 25087 32775 63536 25086 3 63536 25084 0 63536 32767 65535 65520 32767 65535 65520 0 0 0)
  6601.         offset: 0@0).
  6602.     Icons at: #arrow put: (Form
  6603.         extent: 28@19
  6604.         fromArray: #(0 0 0 49152 0 57344 0 61440 0 63488 0 64512 0 65024 32767 65280 32767 65408 32767 65408 32767 65280 0 65024 0 64512 0 63488 0 61440 0 57344 0 49152 0 0 0 0)
  6605.         offset: 0@0).!
  6606.  
  6607. initializeLocations
  6608.     "ModuleCompilerView initializeLocations."
  6609.  
  6610.     Locations _ #(
  6611.         (allVars 10 10)
  6612.         (allCons 10 70)
  6613.         (arrow 65 30)
  6614.         (arrow 65 85)
  6615.         (someVars 100 10)
  6616.         (someCons 100 70)
  6617.         (arrow 155 60)
  6618.         (optimize 190 40)
  6619.         (arrow 245 35)
  6620.         (arrow 245 80)
  6621.         (fewVars 280 27)
  6622.         (fewCons 280 73)).! !
  6623.  
  6624. !ModuleCompilerView class methodsFor: 'instance creation'!
  6625.  
  6626. new
  6627.  
  6628.     ^super new initializeState!
  6629.  
  6630. open
  6631.     "Create and open a new instance of me. Answer the new instance."
  6632.  
  6633.     | extent topView inView |
  6634.     extent _ 350@140.
  6635.     topView _
  6636.         SpecialSystemView
  6637.             model: nil
  6638.             label: ' Compiling a Module '
  6639.             minimumSize: extent.
  6640.     topView addSubView: (inView _ ModuleCompilerView new).
  6641.     topView window: (0@0 extent: extent)
  6642.         viewport: (0@0 extent: extent).
  6643.     topView align: topView viewport center with: (Display boundingBox center + (0@8)).
  6644.     topView translateBy:
  6645.         (topView displayBox amountToTranslateWithin: Display boundingBox).
  6646.     ScheduledControllers schedulePassive: topView controller.
  6647.     ScheduledControllers activeController flushDisplayBits.
  6648.     topView display.
  6649.     ^inView! !
  6650.  
  6651.  
  6652. Model subclass: #Explanation
  6653.     instanceVariableNames: 'thing '
  6654.     classVariableNames: 'Frame '
  6655.     poolDictionaries: ''
  6656.     category: 'ThingLabII-UI-Support'!
  6657. Explanation comment:
  6658. 'I am used as the model for CodeViews on Thing explanations. I support the basic text editing operations (cut, copy, paste, etc) and also the do it, print it, and inspect operations.'!
  6659.  
  6660.  
  6661. !Explanation methodsFor: 'initialization'!
  6662.  
  6663. thing: aThing
  6664.     "Set my Thing."
  6665.  
  6666.     thing _ aThing.! !
  6667.  
  6668. !Explanation methodsFor: 'adaptor'!
  6669.  
  6670. explainText
  6671.     "Answer my Thing's explanation string as a Text object."
  6672.  
  6673.     ^thing explainText asText!
  6674.  
  6675. explainText: newExplanation
  6676.     "Store the new explanation as a string in my Thing."
  6677.  
  6678.     ^thing explainText: newExplanation asString! !
  6679.  
  6680. !Explanation methodsFor: 'text menu'!
  6681.  
  6682. textMenu
  6683.     "Answer a menu of generic text actions."
  6684.  
  6685.     ^ActionMenu
  6686.         labels: 'again\undo\copy\cut\paste\do it\print it\inspect\accept\cancel' withCRs
  6687.         lines: #(2 5 8)
  6688.         selectors: #(again undo copySelection cut paste doIt printIt inspectIt accept cancel)! !
  6689.  
  6690. !Explanation methodsFor: 'doIt support'!
  6691.  
  6692. doItContext
  6693.     "Answer the context in which a text selection can be evaluated."
  6694.  
  6695.     ^nil!
  6696.  
  6697. doItReceiver
  6698.     "Answer the object that should be informed of the result of evaluating a text selection."
  6699.  
  6700.     ^nil!
  6701.  
  6702. doItValue: ignored
  6703.     "I don't do anything with the value of a doIt."! !
  6704. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  6705.  
  6706. Explanation class
  6707.     instanceVariableNames: ''!
  6708.  
  6709.  
  6710. !Explanation class methodsFor: 'instance creation'!
  6711.  
  6712. on: aThing
  6713.     "Answer a new Explanation object for the given Thing."
  6714.  
  6715.     ^(super new) thing: aThing!
  6716.  
  6717. openOn: aThing
  6718.     "Open a CodeView on an Explanation for the given Thing."
  6719.  
  6720.     self openOn: aThing zoomingFrom: nil.!
  6721.  
  6722. openOn: aThing zoomingFrom: fromRect
  6723.     "Open a CodeView on an Explanation for the given Thing, zooming open from the given rectangle if it isn't nil."
  6724.  
  6725.     | textView controller topView zoomFromRect |
  6726.     textView _ CodeView
  6727.         on: (self on: aThing)
  6728.         aspect: #explainText
  6729.         change: #explainText:
  6730.         menu: #textMenu.
  6731.     textView
  6732.         controller: ExplanationController new;
  6733.         borderWidth: 1.
  6734.     controller _ (SpecialSystemController new) fromHolder: self.
  6735.     topView _ SpecialSystemView
  6736.         model: nil
  6737.         label: 'Explanation of ', aThing name
  6738.         minimumSize: 160@50.
  6739.     topView
  6740.         borderWidth: 1;
  6741.         controller: controller;
  6742.         addSubView: textView.
  6743.     (fromRect notNil)
  6744.         ifTrue: [zoomFromRect _ fromRect]
  6745.         ifFalse:
  6746.             [(Frame isNil)
  6747.                 ifTrue: [zoomFromRect _
  6748.                             Display boundingBox center extent: 0@0]
  6749.                 ifFalse: [zoomFromRect _ Frame center extent: 0@0]].
  6750.     (Frame notNil)
  6751.         ifTrue:
  6752.             [controller fromFrame: zoomFromRect.
  6753.              Display zoom: zoomFromRect to: Frame duration: 260.
  6754.              topView window: (0@0 extent: Frame extent) viewport: Frame.
  6755.              topView controller openDisplayAt: Frame center]
  6756.         ifFalse: [topView controller open].! !
  6757.  
  6758. !Explanation class methodsFor: 'accessing'!
  6759.  
  6760. lastFrame: aDisplayRect
  6761.  
  6762.     Frame _ aDisplayRect.! !
  6763.  
  6764. OrderedCollection variableSubclass: #Plan
  6765.     instanceVariableNames: ''
  6766.     classVariableNames: ''
  6767.     poolDictionaries: ''
  6768.     category: 'ThingLabII'!
  6769. Plan comment:
  6770. 'A Plan is an ordered list of constraints to execute to make the current constraint graph consistent.'!
  6771.  
  6772.  
  6773. !Plan methodsFor: 'interpretation'!
  6774.  
  6775. execute
  6776.     "Execute my constraints in order."
  6777.  
  6778.     self do: [: c | c execute].! !
  6779.  
  6780. Object subclass: #ModuleDisjunction
  6781.     instanceVariableNames: 'constEquations knownValue '
  6782.     classVariableNames: ''
  6783.     poolDictionaries: ''
  6784.     category: 'ThingLabII-Module Compiler'!
  6785. ModuleDisjunction comment:
  6786. 'I represent a disjunction (OR) of terms. ThingData
  6787.  
  6788. Each term has the form:
  6789.     aStrength <= aWalkEquation
  6790.  
  6791. I store my terms as an OrderedCollection of Arrays of the form:
  6792.     (aStrength, aWalkEquation)
  6793.  
  6794. Some of my terms can be evaluated at compile time. Any term that evaluates to ''false'' may be removed, as a false term cannot make the overall disjunction be true. On the other hand, any term that evaluates to ''true'' makes the entire disjunction evaluate to true, regardless of the other terms. A conjunction with no terms is false. (Such a conjunction probably had ''false'' terms that were removed during simplification.)
  6795.  
  6796. Instance variables:
  6797.     constEquations...        an OrderedCollection of pairs: (strength, walkEqn)
  6798.     knownValue...            caches the simplified value of this disjunction
  6799.                         (true or false) if it is known at this time or
  6800.                         nil if it cannot be determined at this time.'!
  6801.  
  6802.  
  6803. !ModuleDisjunction methodsFor: 'initialize-release'!
  6804.  
  6805. initialize
  6806.  
  6807.     constEquations _ OrderedCollection new.
  6808.     knownValue _ nil.! !
  6809.  
  6810. !ModuleDisjunction methodsFor: 'operations'!
  6811.  
  6812. addTermsTo: anEquation
  6813.     "Append all my terms to the given equation."
  6814.  
  6815.     constEquations do:
  6816.         [: term |
  6817.          anEquation strength: (term at: 1) weakerOrEq: (term at: 2)].!
  6818.  
  6819. hasOnlyOneTerm
  6820.     "Answer true if this equation has only a single term."
  6821.  
  6822.     ^constEquations size == 1!
  6823.  
  6824. isFalse
  6825.     "Answer true if this set of equations can be evaluated to false at this time."
  6826.  
  6827.     (knownValue isNil) ifTrue: [self simplify].
  6828.     ^knownValue == false!
  6829.  
  6830. isTrue
  6831.     "Answer true if this set of equations can be evaluated to true at this time."
  6832.  
  6833.     (knownValue isNil) ifTrue: [self simplify].
  6834.     ^knownValue == true!
  6835.  
  6836. strength: aStrength weakerOrEq: strengthOrWalkEquation
  6837.     "Add an equation of the form:
  6838.         strength <= walkEquation
  6839.     strengthOrWalkEquation is a Strength or a WalkEquation. If it is a strength, it is converted into a WalkEquation. aStrength is a Strength constant."
  6840.  
  6841.     | eqn |
  6842.     eqn _ (strengthOrWalkEquation isMemberOf: Strength)
  6843.         ifTrue: [WalkEquation constant: strengthOrWalkEquation asSymbol]
  6844.         ifFalse: [strengthOrWalkEquation].
  6845.     constEquations add: (Array with: aStrength with: eqn).
  6846.     knownValue _ nil.! !
  6847.  
  6848. !ModuleDisjunction methodsFor: 'printing'!
  6849.  
  6850. printLeft: left right: right on: aStream
  6851.  
  6852.     left printOn: aStream.
  6853.     aStream nextPutAll: ' .le. '.
  6854.     right printOn: aStream.
  6855.     aStream cr.!
  6856.  
  6857. printOn: aStream
  6858.  
  6859.     aStream nextPutAll: 'OR('.
  6860.     constEquations do:
  6861.         [: eqn | self printLeft: (eqn at: 1) right: (eqn at: 2) on: aStream].
  6862.     aStream nextPutAll: ')'.! !
  6863.  
  6864. !ModuleDisjunction methodsFor: 'code generation'!
  6865.  
  6866. codeLeft: left right: right on: aStream
  6867.     "Used by storeOn: to store a single term of a boolean strength equation. left may be a Strength or a ModuleVarTableEntry."
  6868.  
  6869.     aStream nextPut: $(.
  6870.     (left isMemberOf: ModuleVarTableEntry)
  6871.         ifTrue: [left strengthCodeStringOn: aStream]
  6872.         ifFalse: [left storeOn: aStream].
  6873.     aStream nextPutAll: ' leq: '; cr; tab; tab.
  6874.     (right isMemberOf: ModuleVarTableEntry)
  6875.         ifTrue: [right strengthCodeStringOn: aStream]
  6876.         ifFalse: [right storeOn: aStream].
  6877.     aStream nextPut: $).!
  6878.  
  6879. storeOn: aStream
  6880.     "Append to aStream code to be compiled to evalute myself at run-time."
  6881.  
  6882.     (self isTrue) ifTrue: [^aStream nextPutAll: 'true'].
  6883.     (self isFalse) ifTrue: [^aStream nextPutAll: 'false'].
  6884.     aStream nextPut: $(.
  6885.     constEquations do:
  6886.         [: eqn |
  6887.          aStream tab.
  6888.          self codeLeft: (eqn at: 1) right: (eqn at: 2) on: aStream.
  6889.          aStream nextPutAll: ' | '].
  6890.     (constEquations isEmpty) ifFalse:
  6891.         [aStream skip: -2].
  6892.     aStream nextPut: $).! !
  6893.  
  6894. !ModuleDisjunction methodsFor: 'private'!
  6895.  
  6896. emptyCheck
  6897.     "See if I have no terms and, if so, set my knownValue based on this."
  6898.     "An empty disjunction (OR) is false because the false constant terms were filtered out."
  6899.  
  6900.     (constEquations isEmpty)
  6901.         ifTrue: [knownValue _ false].!
  6902.  
  6903. keepTermLeft: left right: right
  6904.     "This method is used in simplifying module boolean equations. Answer true if the given term should be kept. Set the known value of the equation if possible. Assume that left side is a constant and that the right side has a constant part."
  6905.     "Since this equation is a disjunction (OR), we can remove all false constant terms.  A true constant term makes the entire disjunction true."
  6906.  
  6907.     (left stronger: right constant)
  6908.         ifTrue: [^false]    "term is false, don't keep it"
  6909.         ifFalse:
  6910.             [(right vars isEmpty)
  6911.                 ifTrue:
  6912.                     ["term is true, keep it and set known value"
  6913.                      knownValue _ true.
  6914.                      ^true]
  6915.                 ifFalse:
  6916.                     ["term value is not known, keep it"
  6917.                      ^true]].!
  6918.  
  6919. simplify
  6920.     "Simplify this equation by removing constant terms and setting its known value if possible. A constant term is one for which either:
  6921.     a. the left and right sides are both constants and the left side
  6922.         is NOT STRONGER than the right side (the term is true), or
  6923.     b. the left side is a constant and is STRONGER than the
  6924.         constant part of the right hand side (the term is false)."
  6925.  
  6926.     | newEquations left right |
  6927.     knownValue _ nil.        "assume value cannot be determined"
  6928.     newEquations _ constEquations species new.
  6929.     constEquations do:
  6930.         [: eqn |
  6931.          left _ (eqn at: 1).
  6932.          right _ (eqn at: 2).
  6933.          right simplify.
  6934.          (right constant notNil)
  6935.             ifTrue:    "right hand side has a constant part"
  6936.                 [(self keepTermLeft: left right: right)
  6937.                     ifTrue: [newEquations add: eqn]]
  6938.             ifFalse:    "right hand side has no constant part"
  6939.                 ["term value not known, keep it"
  6940.                  newEquations add: eqn]].
  6941.  
  6942.     constEquations _ newEquations.
  6943.     self emptyCheck.! !
  6944. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  6945.  
  6946. ModuleDisjunction class
  6947.     instanceVariableNames: ''!
  6948.  
  6949.  
  6950. !ModuleDisjunction class methodsFor: 'instance creation'!
  6951.  
  6952. new
  6953.  
  6954.     ^(super new) initialize! !
  6955.  
  6956. Object subclass: #HistoryQueue
  6957.     instanceVariableNames: 'values next '
  6958.     classVariableNames: ''
  6959.     poolDictionaries: ''
  6960.     category: 'ThingLabII-Things-Support'!
  6961. HistoryQueue comment:
  6962. 'I am a simple fixed-length queue that remembers the last <size> elements added to me. The last N elements (where N <= size) may be enumerated from oldest to most recent. The entire queue may be filled with a given value by the clearTo: operation.
  6963.  
  6964. Instance variables:
  6965.     values        -- an <Array> of element values
  6966.     next        -- index of the next location to store an element
  6967. '!
  6968.  
  6969.  
  6970. !HistoryQueue methodsFor: 'all'!
  6971.  
  6972. add: aValue
  6973.     "Add the given value to the end of the queue."
  6974.  
  6975.     values at: next put: aValue.
  6976.     (next = values size)
  6977.         ifTrue: [next _ 1]
  6978.         ifFalse: [next _ next + 1].!
  6979.  
  6980. clearTo: aValue
  6981.  
  6982.     values _ Array new: (values size) withAll: aValue.
  6983.     next _ 1.!
  6984.  
  6985. initialize: size
  6986.  
  6987.     values _ Array new: size.
  6988.     next _ 1.!
  6989.  
  6990. last: count do: aBlock
  6991.     "Evaluate the given block for the last 'count' values, from least to most recent. If 'count' is larger than my size, raise an error."
  6992.  
  6993.     | size i |
  6994.     size _ values size.
  6995.     (count > size) ifTrue: [^self error: 'Queue too small'].
  6996.     i _ ((next - 1 - count) \\ size) + 1.
  6997.     (count = size) ifTrue:
  6998.         [aBlock value: (values at: next).
  6999.          i _ (next = size) ifTrue: [1] ifFalse: [next + 1]].
  7000.     [i ~= next] whileTrue:
  7001.         [aBlock value: (values at: i).
  7002.          (i = size)
  7003.             ifTrue: [i _ 1]
  7004.             ifFalse: [i _ i + 1]].! !
  7005. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  7006.  
  7007. HistoryQueue class
  7008.     instanceVariableNames: ''!
  7009.  
  7010.  
  7011. !HistoryQueue class methodsFor: 'instance creation'!
  7012.  
  7013. new
  7014.  
  7015.     ^self new: 10!
  7016.  
  7017. new: size
  7018.  
  7019.     ^self basicNew initialize: size! !
  7020.  
  7021. Object subclass: #ThingLabII
  7022.     instanceVariableNames: ''
  7023.     classVariableNames: ''
  7024.     poolDictionaries: ''
  7025.     category: 'ThingLabII'!
  7026. ThingLabII comment:
  7027. 'ThingLab II was written by John Maloney and Bjorn N. Freeman-Benson under the guidance of Professor Alan Borning. We would like to acknowledge and thank some of the many other people who have contributed ideas and suggestions for ThingLab II (alphabetically):
  7028.  
  7029.     Yu-Ying Chow
  7030.     Robert Duisberg
  7031.     Theresa Farrah
  7032.     Bjorn N. Freeman-Benson
  7033.     Robert Henry
  7034.     Axel Kramer
  7035.     Frank Ludolph
  7036.     John Maloney
  7037.     Scott Wallace
  7038.     Mike Woolf
  7039.  
  7040. For a complete introduction and overview of the ThingLabII system, please read the ThingLab II Programmer''s Manual that has not yet been written.
  7041.  
  7042. The ThingLabII class is the "anchor" point for the ThingLabII system. Here is where global data such as the current constraint satisfaction planner is kept.'!
  7043.  
  7044. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  7045.  
  7046. ThingLabII class
  7047.     instanceVariableNames: 'lastUniqueNumber editStrength '!
  7048.  
  7049.  
  7050. !ThingLabII class methodsFor: 'class initialization'!
  7051.  
  7052. initialize
  7053.     "ThingLabII initialize."
  7054.  
  7055.     "The first unique number will be 1."
  7056.     lastUniqueNumber _ 0.
  7057.  
  7058.     "Default edit strength is 'preferred'."
  7059.     editStrength _ #preferred.! !
  7060.  
  7061. !ThingLabII class methodsFor: 'access'!
  7062.  
  7063. editStrength
  7064.     "The strength for user editing and manipulation of things with the mouse."
  7065.  
  7066.     ^editStrength!
  7067.  
  7068. editStrength: aSymbol
  7069.     "Set the strength for user editing."
  7070.  
  7071.     editStrength _ aSymbol.! !
  7072.  
  7073. !ThingLabII class methodsFor: 'unique number generation'!
  7074.  
  7075. uniqueNumber
  7076.     "A generator for unique number for Thing and Module names."
  7077.  
  7078.     ^lastUniqueNumber _ lastUniqueNumber + 1! !
  7079.  
  7080. !ThingLabII class methodsFor: 'prototype maintainance'!
  7081.  
  7082. allPartsOf: aPrototype in: initializedClasses
  7083.     "Answer true if the classes for all Thing parts of the given prototype are in the given collection."
  7084.  
  7085.     aPrototype thingPartsDo:
  7086.         [: part |
  7087.          (initializedClasses includes: part class) ifFalse: [^false]].
  7088.     ^true!
  7089.  
  7090. collectPrimitives
  7091.     "Answer a collection of prototypes for all primitive Things."
  7092.  
  7093.     | primitivePrototypes |
  7094.     "Construct a list of all Things that currently exist."
  7095.     primitivePrototypes _ IdentitySet new.
  7096.     SystemOrganization categories do:
  7097.         [: category |
  7098.          (('things*' match: category) and:
  7099.            [('things-built' match: category) not]) ifTrue:
  7100.             [(SystemOrganization listAtCategoryNamed: category asSymbol) do:
  7101.                 [: className |
  7102.                  primitivePrototypes add: (Smalltalk at: className) prototype]]].
  7103.     ^primitivePrototypes asOrderedCollection!
  7104.  
  7105. updatePrimitives
  7106.     "Updates all the primitive Things in the system. Expensive!! This is used after changing the constraints for a primitive Thing to cause prototypes containing this Thing to be updated with new instances having the new prototypes. User-defined Things are not affected."
  7107.     "Note: This algorithm assumes that structure of prototypes (i.e. what parts they have and what types those parts are) has not been changed. If prototype structure has been changed, running this algorithm a second time will take care of matters."
  7108.     "ThingLabII updatePrimitives"
  7109.  
  7110.     | allProtos initializedClasses proto |
  7111.     allProtos _ self collectPrimitives.
  7112.     initializedClasses _ IdentitySet new.
  7113.     [allProtos isEmpty] whileFalse:
  7114.         [proto _ allProtos detect: [: p | self allPartsOf: p in: initializedClasses].
  7115.          Transcript show: 'Initializing ', proto class printString; cr.
  7116.          proto class initialize.
  7117.          allProtos remove: proto.
  7118.          initializedClasses add: proto class.
  7119.          proto destroy.
  7120.          proto _ nil].
  7121.     Transcript show: 'Updating Parts Bins'; cr.
  7122.     PartsBin updateAllBins    .
  7123.     Transcript show: 'All Primitives Updated'; cr.! !
  7124.  
  7125. !ThingLabII class methodsFor: 'filing out'!
  7126.  
  7127. fileOutCategoriesMatching: patternString on: aStream
  7128.     "File out on the given stream all methods in protocol categories matching the given pattern string. Both classes and metaclasses are examined."
  7129.  
  7130.     | class metaClass |
  7131.     Transcript cr; show: '*** Filing out ThingLabII System Changes ***'; cr; cr.
  7132.     (SystemOrganization elements) do:
  7133.         [: className |
  7134.          class _ Smalltalk at: className asSymbol.
  7135.          metaClass _ class class.
  7136.          class organization categories do:
  7137.             [: categoryName |
  7138.              (patternString match: categoryName) ifTrue:
  7139.                 [self
  7140.                     fileOutClass: class
  7141.                     category: categoryName
  7142.                     on: aStream]].
  7143.          metaClass organization categories do:
  7144.             [: categoryName |
  7145.              (patternString match: categoryName) ifTrue:
  7146.                 [self
  7147.                     fileOutClass: metaClass
  7148.                     category: categoryName
  7149.                     on: aStream]]].!
  7150.  
  7151. fileOutClass: aClass category: category on: aStream
  7152.     "File out the given category of the given class on the given stream."
  7153.  
  7154.     Transcript show: aClass printString, '>>', category; cr.
  7155.     aClass
  7156.         fileOutCategory: category
  7157.         on: aStream
  7158.         moveSource: false
  7159.         toFile: 0.!
  7160.  
  7161. fileOutClassesOn: aStream
  7162.     "File out on the given stream all classes in categories matching 'thinglab*'."
  7163.     "WARNING: The order of class initializations will need to be fixed by hand."
  7164.  
  7165.     | classNames classList |
  7166.     Transcript cr; show: '*** Filing out ThingLabII classes ***'; cr.
  7167.     classNames _ OrderedCollection new: 100.
  7168.     SystemOrganization categories do:
  7169.         [: categoryName |
  7170.          ('thinglab*' match: categoryName) ifTrue:
  7171.             [Transcript show: 'Classes in: ', categoryName; cr.
  7172.              classNames addAll:
  7173.                 (SystemOrganization listAtCategoryNamed: categoryName)]].
  7174.     classList _ ChangeSet superclassOrder:
  7175.                 (classNames collect: [: className | Smalltalk at: className]).
  7176.     classList do:
  7177.         [: aClass |
  7178.          aStream cr; cr.
  7179.          aClass fileOutOn: aStream].!
  7180.  
  7181. fileOutPostludeOn: aStream
  7182.     "File out some final stuff on the given stream."
  7183.  
  7184.     aStream cr; cr; nextPutAll:
  7185. '"*************** Class and System Initialization ***************"!!
  7186.  
  7187.     "Put class initializations here (NOTE: verify these and check ordering):"!!
  7188.     ArrowHead initialize!!
  7189.     BusyCursor initialize!!
  7190.     EquationTranslator initialize!!
  7191.     Strength initialize!!
  7192.     ThingLabII initialize!!
  7193.     Thing initialize!!
  7194.     PrimitiveThing initialize!!
  7195.     ModuleCompilerView initialize!!
  7196.     ThingLabIIControlPanel initialize!!
  7197.     PartsBin initialize!!
  7198.  
  7199.     "Initialize the ScreenController yellow button menu:"!!
  7200.     ScreenController initialize!!
  7201.     ScreenController allInstancesDo: [: c | c initializeYellowButtonMenu]!!
  7202.  
  7203. "Th-th-that''s all, Folks..."!!'.!
  7204.  
  7205. fileOutPreludeOn: aStream with: nameString
  7206.     "File out the time and copyright notice."
  7207.  
  7208.     aStream nextPutAll:
  7209.         '"', nameString, ' of ', Time dateAndTimeNow printString, '"!!'; cr; cr.
  7210.     aStream nextPutAll:
  7211. '"Copyright (c) 1989 and 1990, Regents of the University of Washington.
  7212. Permission is granted to use or reproduce this program for research
  7213. and development purposes only. For information regarding the use of this
  7214. program in a commercial product, contact:
  7215.  
  7216.     Office of Technology Transfer
  7217.     University of Washington
  7218.     4225 Roosevelt Way NE, Suite 301
  7219.     Seattle, WA  98105
  7220.  
  7221. ThingLab II was written between 1988 and 1990 by John Maloney and
  7222. Bjorn N. Freeman-Benson with the guidance of Alan Borning."!!'; cr.!
  7223.  
  7224. fileOutPrimitiveThingsOn: aStream
  7225.     "Files out all the primitive Things in the system on the given stream. The primitives are filed out in the correct order."
  7226.     "ThingLabII fileOutPrimitiveThingsOn: (FileStream newFileNamed: 'Things.st')"
  7227.  
  7228.     | allProtos filedOutClasses proto |
  7229.     Transcript cr; show: '*** Filing out ThingLabII Primitive Things ***'; cr.
  7230.     self fileOutPreludeOn: aStream with: 'ThingLabII Primitive Things'.
  7231.     allProtos _ self collectPrimitives.
  7232.     filedOutClasses _ IdentitySet new.
  7233.     [allProtos isEmpty] whileFalse:
  7234.         [proto _ allProtos detect:
  7235.             [: p |
  7236.              ((p class superclass == PrimitiveThing) or:
  7237.                 [filedOutClasses includes: p class superclass]) and:
  7238.               [self allPartsOf: p in: filedOutClasses]].
  7239.          (proto isNil) ifTrue:
  7240.             [self error: 'Circular dependency among Primitive things'].
  7241.          proto class fileOutOn: aStream.
  7242.          aStream cr.
  7243.          allProtos remove: proto.
  7244.          filedOutClasses add: proto class].
  7245.     aStream cr; close.
  7246.     Transcript cr; cr; show: '*** Primitive Things Filed Out ***'; cr; cr.!
  7247.  
  7248. fileOutSystemOn: aStream
  7249.     "File out the ThingLabII system on the given stream. This includes all classes and all changes to system classes. It does not include the primitive Things. You may need to adjust the order of the 'initialize' messages listed in fileOutPostludeOn:. You will definitely need to remove the class initialization messages sprinkled throughout the file."
  7250.     "ThingLabII fileOutSystemOn: (FileStream newFileNamed: 'ThingLabII.st')"
  7251.  
  7252.     self fileOutPreludeOn: aStream with: 'ThingLabII System'.
  7253.     self fileOutCategoriesMatching: 'thinglab*' on: aStream.
  7254.     self fileOutClassesOn: aStream.
  7255.     self fileOutPostludeOn: aStream.
  7256.     aStream cr; close.
  7257.     Transcript cr; cr; show: '***ThingLabII System Filed Out***'; cr; cr.! !
  7258.  
  7259.  
  7260. Object subclass: #Reference
  7261.     instanceVariableNames: 'root path part putSymbol finalVarCache '
  7262.     classVariableNames: ''
  7263.     poolDictionaries: ''
  7264.     category: 'ThingLabII'!
  7265. Reference comment:
  7266. 'A reference is used to point to some part or sub-part of a Thing. It consists of a root Thing and a path. The path is the sequence of parts to traverse, starting from the Thing, to get to the referenced part.
  7267.  
  7268. Instance variables:
  7269.     variable            the Thing from which the path starts <Thing>
  7270.     path            an array of part names that goes from the root
  7271.                     to one part above the final destination {Symbol}
  7272.     part                the final path element <Symbol>
  7273.     putSymbol        the selector to send to the destination Thing to
  7274.                     set its value <Symbol>. This is expensive to
  7275.                     compute, so it is cached.
  7276.     finalVarCache    the final Thing in the path. It is to the final variable
  7277.                     that the get and put messages are sent. The final
  7278.                     variable is expensive to compute, so it is cached.
  7279. '!
  7280.  
  7281.  
  7282. !Reference methodsFor: 'initialize-release'!
  7283.  
  7284. destroy
  7285.     "Break circular dependencies."
  7286.  
  7287.     root _ nil.
  7288.     path _ nil.
  7289.     part _ nil.
  7290.     putSymbol _ nil.
  7291.     finalVarCache _ nil.!
  7292.  
  7293. on: aThing path: thePath
  7294.     "Initialize myself to point to the part of aThing accessed by the given sequence of selectors (thePath). thePath may contain Symbols or Strings."
  7295.  
  7296.     root _ aThing.
  7297.     path _ (thePath copyFrom: 1 to: (thePath size - 1)) asArray.
  7298.     part _ thePath last asSymbol.
  7299.     putSymbol _ nil.        "computed on demand"
  7300.     finalVarCache _ nil.    "computed on demand"! !
  7301.  
  7302. !Reference methodsFor: 'access'!
  7303.  
  7304. finalVariable
  7305.     "Follow the path and answer the object found at the end. This is the immediate parent of the variable I reference."
  7306.  
  7307.     (finalVarCache isNil) ifTrue:
  7308.         [finalVarCache _
  7309.             path inject: root
  7310.             into: [: v : p | v perform: p]].
  7311.     ^finalVarCache!
  7312.  
  7313. finalVarPath
  7314.  
  7315.     ^path!
  7316.  
  7317. fullPath
  7318.  
  7319.     ^path copyWith: part!
  7320.  
  7321. part
  7322.  
  7323.     ^part!
  7324.  
  7325. root
  7326.  
  7327.     ^root!
  7328.  
  7329. root: aThing
  7330.     "Set my root Thing. Used during module compilation."
  7331.  
  7332.     root _ aThing.
  7333.     finalVarCache _ nil.    "flush cache"! !
  7334.  
  7335. !Reference methodsFor: 'target access'!
  7336.  
  7337. cleanUpThingData
  7338.     "Remove the thingData for the object I point to if it has no more constraints."
  7339.  
  7340.     (self finalVariable) cleanUpThingDataFor: part.!
  7341.  
  7342. thingData
  7343.     "Answer the ThingData for the object I reference or nil if one doesn't currently exist."
  7344.  
  7345.     ^(self finalVariable) thingDataFor: part!
  7346.  
  7347. thingDataOrAllocate
  7348.     "Answer a ThingData for the object I reference, allocating a new one if one doesn't currently exist."
  7349.  
  7350.     ^(self finalVariable) thingDataOrAllocateFor: part!
  7351.  
  7352. value
  7353.     "Answer the value of the object that I reference."
  7354.  
  7355.     ^(self finalVariable) perform: part!
  7356.  
  7357. value: anObject
  7358.     "Set the value of the object that I reference."
  7359.  
  7360.     ^(self finalVariable)
  7361.         perform: self putSymbol
  7362.         with: anObject! !
  7363.  
  7364. !Reference methodsFor: 'testing'!
  7365.  
  7366. = aReference
  7367.  
  7368.     (aReference isMemberOf: Reference) ifFalse: [^false].
  7369.     ^(root == aReference root) and:
  7370.         [self fullPath = aReference fullPath]!
  7371.  
  7372. isPrefixOf: aPath 
  7373.     "Answer true I am a prefix of aPath."
  7374.  
  7375.     (aPath size < (path size + 1)) ifTrue: [^false].
  7376.     1 to: path size do:
  7377.         [: i |
  7378.          ((aPath at: i) = (path at: i))
  7379.             ifFalse: [^false]].
  7380.     ^(aPath at: (path size + 1)) = part! !
  7381.  
  7382. !Reference methodsFor: 'functions'!
  7383.  
  7384. , aSymbolArray 
  7385.     "Create a new Reference that is a copy of myself extending my path by aSymbolArray. For example,
  7386.  
  7387.     ref1, #(d e f)
  7388.  
  7389. will create a new reference with the path such as 'a.b.c.d.e.f' given that ref1's path was 'a.b.c'."
  7390.  
  7391.     ^Reference
  7392.         on: root
  7393.         path: (self fullPath, aSymbolArray)!
  7394.  
  7395. copyFromTopParent
  7396.     "Create a new reference that refers to the same part that I do, but it goes from the top-most parent."
  7397.  
  7398.     ^Reference
  7399.         on: root topParent
  7400.         path: (root allTopParentPaths first, self fullPath)!
  7401.  
  7402. putSymbol
  7403.     "Answer the putSymbol for the object I reference. The put symbol is computed the first time it is needed, then cached for future use."
  7404.  
  7405.     (putSymbol isNil)
  7406.         ifTrue: [putSymbol _ ('prim', part, ':') asSymbol].
  7407.     ^putSymbol!
  7408.  
  7409. refresh
  7410.     "Purge my finalVar cache. This is used when the structure of a Thing is changed during merging or unmerging or when the root is changed."
  7411.  
  7412.     finalVarCache _ nil.!
  7413.  
  7414. topParent
  7415.     "Answer the top-most parent of my root Thing."
  7416.  
  7417.     ^root topParent! !
  7418.  
  7419. !Reference methodsFor: 'cloning'!
  7420.  
  7421. cloneUsing: cloneDictionary
  7422.     "Make a clone of myself using the mapping given by cloneDictionary."
  7423.  
  7424.     | myClone |
  7425.     myClone _ self shallowCopy.
  7426.     myClone root: (cloneDictionary at: root).
  7427.     ^myClone! !
  7428.  
  7429. !Reference methodsFor: 'printing'!
  7430.  
  7431. longName
  7432.  
  7433.     | s |
  7434.     s _ (String new: 100) writeStream.
  7435.     self fullPath do:
  7436.         [: partName |
  7437.          s nextPutAll: partName.
  7438.          s nextPut: $..].
  7439.     s skip: -1.
  7440.     ^s contents!
  7441.  
  7442. longPrintOn: aStream
  7443.  
  7444.     (root isThing)
  7445.         ifTrue: [root shortPrintOn: aStream]
  7446.         ifFalse: [root printOn: aStream].
  7447.     aStream nextPut: $..
  7448.     path do: [: p | p printOn: aStream. aStream nextPut: $.].
  7449.     part printOn: aStream.!
  7450.  
  7451. printOn: aStream
  7452.     "Usually we show more information when the shift key is held down but in this case we show less. This is to reduce verbiage when printing constraints and methods and also to help you see more clearly when different constraints refer to the same variable."
  7453.  
  7454.     (Sensor leftShiftDown)
  7455.         ifTrue: [self shortPrintOn: aStream]
  7456.         ifFalse: [self longPrintOn: aStream].!
  7457.  
  7458. shortPrintOn: aStream
  7459.  
  7460.     self finalVariable shortPrintOn: aStream.
  7461.     aStream nextPutAll: '.', part.! !
  7462. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  7463.  
  7464. Reference class
  7465.     instanceVariableNames: ''!
  7466.  
  7467.  
  7468. !Reference class methodsFor: 'instance creation'!
  7469.  
  7470. on: aThing path: anArrayOfSymbols
  7471.     "Answer a Reference for the part of aThing with the given path."
  7472.  
  7473.     ^(self new) on: aThing path: anArrayOfSymbols! !
  7474.  
  7475. Object subclass: #Constraint
  7476.     instanceVariableNames: 'strength symbols variables thingDatas methods inverseMethods whichMethod flags '
  7477.     classVariableNames: ''
  7478.     poolDictionaries: ''
  7479.     category: 'ThingLabII-Constraints'!
  7480. Constraint comment:
  7481. 'I represent a system-maintainable relationship, or "constraint", between a set of variables. I contain a set of methods that can be executed to enforce the constraint. If I am satisfied in the current data flow graph, the method used to enforce, or "satisfy", this constraint is stored in whichMethod. If I am not satisfied, whichMethod will be nil.
  7482.  
  7483. Note: Constraints must only be applied to the leaves of the Thing data hierarchy because there is currently no support for constraints at different levels (such as one constraint on a Point and another on its X part).
  7484.  
  7485. Instance variables:
  7486.  
  7487.     variables...        references to the variables to which this
  7488.                     constraint applies {Reference}
  7489.     strength...        the strength of this constraint <Strength>
  7490.     methods...        a collection of methods that can be used to
  7491.                     enforce this constraint {Method}
  7492.     whichMethod...    the method currently used to enforce this constraint
  7493.                     or nil if this constraint is not satisfied <Method>'!
  7494.  
  7495.  
  7496. !Constraint methodsFor: 'initialize-release'!
  7497.  
  7498. bind: refs strength: aSymbol
  7499.     "Bind myself to the given set of references with the given strength."
  7500.  
  7501.     self isBound
  7502.         ifTrue: [self notify: 'This constraint is already bound!!'].
  7503.     self variables: refs.
  7504.     strength _ Strength of: aSymbol.!
  7505.  
  7506. destroy
  7507.  
  7508.     strength _ nil.
  7509.     symbols _ nil.
  7510.     variables _ nil.
  7511.     thingDatas _ nil.
  7512.     methods _ nil.
  7513.     inverseMethods _ nil.
  7514.     whichMethod _ nil.
  7515.     flags _ nil.!
  7516.  
  7517. initializeFlags
  7518.     "Set a multiple output flag if this constraint has at least one method with multiple outputs. Clear other flags."
  7519.     "WARNING: This method assumes that 'methods' has already been initialized."
  7520.  
  7521.     flags _ 0.
  7522.     methods do:
  7523.         [: m |
  7524.          ((m bindings select: [: b | b == $o]) size > 1) ifTrue:
  7525.             [flags _ flags bitOr: 2r100]].!
  7526.  
  7527. symbols: symbolList methods: methodList
  7528.     "Initialize myself with the given methods. I am initialially unbound."
  7529.  
  7530.     strength _ #unbound.
  7531.     symbols _ symbolList.
  7532.     variables _ Array new: symbolList size.
  7533.     thingDatas _ Array new: symbolList size.
  7534.     self methods: methodList asArray.
  7535.     whichMethod _ nil.
  7536.     self initializeFlags.! !
  7537.  
  7538. !Constraint methodsFor: 'DeltaBlue-public'!
  7539.  
  7540. addConstraint
  7541.     "Add this constraint to the constraint graph and attempt to satisfy it."
  7542.  
  7543.     self variables: variables.    "make sure thingDatas cache is up to date"
  7544.     self addToGraph.
  7545.     DeltaBluePlanner incrementalAdd: self.!
  7546.  
  7547. removeConstraint
  7548.     "Remove the constraint from the constraint graph, possible causing other constraints to be satisfied."
  7549.  
  7550.     DeltaBluePlanner incrementalRemove: self.
  7551.     self removeFromGraph.
  7552.     variables do: [: var | var cleanUpThingData].! !
  7553.  
  7554. !Constraint methodsFor: 'DeltaBlue-private'!
  7555.  
  7556. addToGraph
  7557.     "Add myself to the constraint graph as an unsatisfied constraint."
  7558.  
  7559.     thingDatas do:
  7560.         [: td |
  7561.          td addConstraint: self.
  7562.          (td determinedBy == self) ifTrue:
  7563.             [td determinedBy: nil].
  7564.          td removeUsedBy: self].
  7565.     whichMethod _ nil.!
  7566.  
  7567. calculateDeltaBlueData: execFlag
  7568.     "Calculate the walkabout strength, the stay flag, and (if execFlag is true) the real data values for the current outputs of this constraint. Answer a collection of ThingDatas for the outputs."
  7569.  
  7570.     | stayFlag |
  7571.     "assume: whichMethod has been set"
  7572.     "My outputs are stay if either:
  7573.         I am a stay constraint OR
  7574.         I am not an input constraint such as a mouse constraint and
  7575.          all the inputs of my selected method are stay."
  7576.     stayFlag _
  7577.         self isStay or:
  7578.           [(self isInput not) and:
  7579.            [whichMethod inputsAreStayIn: thingDatas]].
  7580.     (execFlag & stayFlag) ifTrue:
  7581.         [whichMethod execute: variables].
  7582.     ^whichMethod updateOutputsIn: thingDatas for: self stay: stayFlag!
  7583.  
  7584. execute
  7585.     "Execute my selected method, if any."
  7586.  
  7587.     (whichMethod notNil) ifTrue:
  7588.         [whichMethod execute: variables].!
  7589.  
  7590. hasMultipleOutputs
  7591.     "Answer true if this constraint has at least one method that has multiple outputs."
  7592.  
  7593.     ^0 ~= (flags bitAnd: 2r100)!
  7594.  
  7595. inputsKnown: currentMark
  7596.     "Answer true if all the inputs of my selected method have the given mark."
  7597.  
  7598.     ^whichMethod inputsIn: thingDatas known: currentMark!
  7599.  
  7600. removeFromGraph
  7601.     "Remove myself from the constraint graph."
  7602.  
  7603.     thingDatas do:
  7604.         [: td |
  7605.          td removeConstraint: self.
  7606.          (td determinedBy == self) ifTrue:
  7607.             [td determinedBy: nil].
  7608.          td removeUsedBy: self].
  7609.     whichMethod _ nil.!
  7610.  
  7611. satisfyWith: aMethod
  7612.     "Satisfy myself using the given method."
  7613.  
  7614.     | bindings i last td |
  7615.     whichMethod _ aMethod.
  7616.     bindings _ whichMethod bindings.
  7617.     i _ 1.
  7618.     last _ bindings size.
  7619.     [i <= last] whileTrue:
  7620.         [td _ thingDatas at: i.
  7621.          ((bindings at: i) == $i) ifTrue:
  7622.             [td addUsedBy: self].
  7623.          ((bindings at: i) == $o) ifTrue:
  7624.             [td determinedBy: self].
  7625.          i _ i + 1].!
  7626.  
  7627. selectMethodsGiven: currentMark
  7628.     "Answer a collection of my methods that change the weakest of my variables and do not change any previously determined (i.e. marked) variable. Answer nil if there is no such method."
  7629.  
  7630.     | minOutStrength possibleMethods strongestOut bestMethods |
  7631.     minOutStrength _ Strength absoluteStrongest.
  7632.     possibleMethods _ OrderedCollection new: 20.
  7633.     methods do:
  7634.         [: method |
  7635.          ((method outputsIn: thingDatas notKnown: currentMark) and:
  7636.           [method isPossibleMethodGiven: strength]) ifTrue:
  7637.              [strongestOut _ method strongestOutStrengthIn: thingDatas.
  7638.              possibleMethods addFirst:
  7639.                 (Array with: method with: strongestOut).
  7640.              (strongestOut weaker: minOutStrength) ifTrue:
  7641.                 [minOutStrength _ strongestOut]]].
  7642.  
  7643.     "if this constraint is not stronger than some possible set of outputs, leave it unsatisfied"
  7644.     (self strength weaker: minOutStrength) ifTrue:
  7645.         [^#()].
  7646.  
  7647.     "collect and answer the methods that change the weakest set of outputs"
  7648.     bestMethods _ OrderedCollection new: 20.
  7649.     possibleMethods do:
  7650.         [: methodAndStrength |
  7651.          ((methodAndStrength at: 2) sameAs: minOutStrength) ifTrue:
  7652.             [bestMethods add: (methodAndStrength at: 1)]].
  7653.  
  7654.     ^bestMethods!
  7655.  
  7656. strengthsFor: aMethod
  7657.     "Answer the walkabout strengths to be assigned to the outputs of the given method. The walkabout strength is the strength required to override the weakest upstream constraint determining the value of a given variable. The computation is complicated by the fact that some of my methods may not have inverses."
  7658.  
  7659.     | outStrengths bindings i outStrength strongestOutOfInverse |
  7660.     outStrengths _ OrderedCollection new: bindings size * 2.
  7661.     bindings _ aMethod bindings.
  7662.     i _ bindings size.
  7663.     [i > 0] whileTrue:
  7664.         [((bindings at: i) == $o) ifTrue:
  7665.             [outStrength _ self strength.
  7666.              (inverseMethods at: i) do:
  7667.                 [: inverse |
  7668.                  strongestOutOfInverse _
  7669.                     (methods at: inverse) strongestOutStrengthIn: thingDatas.
  7670.                  outStrength _
  7671.                     outStrength weakest: strongestOutOfInverse].
  7672.             outStrengths addLast: outStrength].
  7673.          i _ i - 1].
  7674.     ^outStrengths!
  7675.  
  7676. unsatisfy
  7677.     "Unsatisfy myself. Remove myself from the usedBy and determinedBy fields of my argument thingDatas and set whichMethod to nil. This is a noop if I am already unsatisfied."
  7678.  
  7679.     | bindings i td |
  7680.     (whichMethod notNil) ifTrue:
  7681.         [bindings _ whichMethod bindings.
  7682.          i _ thingDatas size.
  7683.          [i > 0] whileTrue:
  7684.             [td _ thingDatas at: i.
  7685.              (td determinedBy == self) ifTrue:
  7686.                 [td determinedBy: nil].
  7687.              ((bindings at: i) == $i) ifTrue:
  7688.                 [td removeUsedBy: self].
  7689.              i _ i - 1].
  7690.          whichMethod _ nil].! !
  7691.  
  7692. !Constraint methodsFor: 'Blue-private'!
  7693.  
  7694. attemptSatisfaction: currentMark
  7695.     "Consider myself for possible satisfaction. If I can be satisfied, answer the chosen method. Otherwise, answer nil. The outcome of considering a constraint for satisfaction may be:
  7696.     1. it is established that the constraint can never be satisfied,
  7697.     2. the constraint can be satisfied with some method, or
  7698.     3. we don't know the values of enough variables to choose a method to satisfy the constraint at this time"
  7699.  
  7700.     | possible chosen |
  7701.     (self shouldConsider not | self isCommitted) ifTrue:
  7702.         [^nil].    "this constraint is already committed or is not ready for consideration"
  7703.  
  7704.     possible _ false.    "assume false until shown otherwise"
  7705.     methods reverseDo:
  7706.         [: m |
  7707.          (m outputsIn: thingDatas notKnown: currentMark) ifTrue:
  7708.             [possible _ true.    "a possible method"
  7709.              (m inputsIn: thingDatas known: currentMark) ifTrue:
  7710.                 [chosen _ m]]].
  7711.     (possible) ifFalse:
  7712.         ["this constraint can never be satisfied"
  7713.          self setCommitted.
  7714.          ^nil].
  7715.     (chosen notNil)
  7716.          ifTrue:
  7717.             ["satisfy this constraint using the chosen method"
  7718.              self reconsiderConstraintsOnOutputsOf: chosen mark: currentMark.
  7719.               self setCommitted.
  7720.              ^chosen]
  7721.         ifFalse:
  7722.             ["don't consider this constraint until another var is known"
  7723.              self clearConsider.
  7724.              ^nil].!
  7725.  
  7726. clearCommitted
  7727.     "Clear my committed flag."
  7728.  
  7729.     flags _ flags bitAnd: (2r010 bitInvert)!
  7730.  
  7731. clearConsider
  7732.     "Clear my consider flag."
  7733.  
  7734.     flags _ flags bitAnd: (2r001 bitInvert)!
  7735.  
  7736. isCommitted
  7737.     "Answer true if my committed flag is set."
  7738.  
  7739.     ^0 ~~ (flags bitAnd: 2r010)!
  7740.  
  7741. prepareForPlanning
  7742.     "Prepare for planning using the Blue planner. No constraints are committed yet. Only constraints with no inputs are worthy of initial consideration."
  7743.  
  7744.     self clearCommitted.
  7745.     self clearConsider.
  7746.     methods do:
  7747.         [: m |
  7748.          (m bindings includes: $i) ifFalse:
  7749.             ["give this constraint initial consideration only if it has a method with zero inputs"
  7750.              self setConsider.
  7751.              ^self]].!
  7752.  
  7753. reconsiderConstraintsOnOutputsOf: aMethod mark: currentMark
  7754.     "Mark for possible reconsideration all constraints on the output variables of the given method."
  7755.  
  7756.     aMethod outDatasIn: thingDatas do:
  7757.         [: out |
  7758.          out mark: currentMark.
  7759.          out constraints do:
  7760.             [: c | c setConsider]].!
  7761.  
  7762. setCommitted
  7763.     "Set my committed flag."
  7764.  
  7765.     flags _ flags bitOr: 2r010.!
  7766.  
  7767. setConsider
  7768.     "Set my consider flag."
  7769.  
  7770.     flags _ flags bitOr: 2r001.!
  7771.  
  7772. shouldConsider
  7773.     "Answer true if my consider flag is set."
  7774.  
  7775.     ^0 ~~ (flags bitAnd: 2r001)! !
  7776.  
  7777. !Constraint methodsFor: 'access'!
  7778.  
  7779. inDatas
  7780.     "Answer the ThingDatas for the inputs of my currently selected method."
  7781.  
  7782.     | inDatas |
  7783.     inDatas _ OrderedCollection new: thingDatas size * 2.
  7784.     whichMethod inDatasIn: thingDatas do:
  7785.         [: in | inDatas add: in].
  7786.     ^inDatas!
  7787.  
  7788. methods
  7789.     "Answer my complete set of methods."
  7790.  
  7791.     ^methods!
  7792.  
  7793. methods: methodArray
  7794.     "Set my set of methods and record their inverses. The inverseMethods array contains, for each variable of this constraint, an array of indices for the methods that have that variable as an input."
  7795.  
  7796.     methods _ methodArray.
  7797.     inverseMethods _ (1 to: variables size) collect:
  7798.         [: inputIndex |
  7799.          (1 to: methods size) select:
  7800.             [: methodIndex |
  7801.              ((methods at: methodIndex) bindings at: inputIndex) == $i]].!
  7802.  
  7803. outDatas
  7804.     "Answer the ThingDatas for the outputs of my currently selected method."
  7805.  
  7806.     | outDatas |
  7807.     outDatas _ OrderedCollection new: thingDatas size * 2.
  7808.     whichMethod outDatasIn: thingDatas do:
  7809.         [: out | outDatas add: out].
  7810.     ^outDatas!
  7811.  
  7812. outDatasDo: aBlock
  7813.     "Evaluate the given block for all outputs of my currently selected method."
  7814.  
  7815.     whichMethod outDatasIn: thingDatas do: aBlock.!
  7816.  
  7817. strength
  7818.     "Answer my strength."
  7819.  
  7820.     ^strength!
  7821.  
  7822. strength: aStrength
  7823.     "Set my strength."
  7824.  
  7825.     strength _ aStrength.!
  7826.  
  7827. symbols
  7828.     "Answer a collection of symbolic names for my arguments. Each symbol in this collection is used to refer to the variable at the same location in the variables list."
  7829.  
  7830.     ^symbols!
  7831.  
  7832. thingDatas
  7833.     "Answer the cache of ThingDatas for my variables."
  7834.  
  7835.     ^thingDatas!
  7836.  
  7837. variables
  7838.     "Answer my variables (a collection of References)."
  7839.  
  7840.     ^variables!
  7841.  
  7842. variables: arrayOfReferences
  7843.     "Set my variables and compute the thingDatas cache."
  7844.  
  7845.     variables _ arrayOfReferences.
  7846.     thingDatas _ variables collect: [: ref | ref refresh; thingDataOrAllocate].!
  7847.  
  7848. whichMethod
  7849.     "Answer the method that I use to satisfy myself in the current solution. This is nil if I am not currently satisfied."
  7850.  
  7851.     ^whichMethod!
  7852.  
  7853. whichMethod: aMethod
  7854.     "Set the method that I use to satisfy myself in the current solution."
  7855.  
  7856.     whichMethod _ aMethod.! !
  7857.  
  7858. !Constraint methodsFor: 'applying'!
  7859.  
  7860. add: aStrengthSymbol on: r1 on: r2
  7861.     "Add a copy of this constraint to the given references with the given strength. The receiver must be an unbound constraint."
  7862.  
  7863.     ^((self clone)
  7864.         bind: (Array with: r1 with: r2)
  7865.         strength: aStrengthSymbol)
  7866.             addConstraint!
  7867.  
  7868. add: aStrengthSymbol on: r1 on: r2 on: r3
  7869.     "Add a copy of this constraint to the given references with the given strength. The receiver must be an unbound constraint."
  7870.  
  7871.     ^((self clone)
  7872.         bind: (Array with: r1 with: r2 with: r3)
  7873.         strength: aStrengthSymbol)
  7874.             addConstraint! !
  7875.  
  7876. !Constraint methodsFor: 'queries'!
  7877.  
  7878. doesSomething
  7879.     "Some constraints, such as Stay and Edit constraints, are used only to control the planning process and have no actual code to execute. Answer false if I am such a constraint, otherwise answer true (the default behavior)."
  7880.  
  7881.     ^true!
  7882.  
  7883. isBound
  7884.     "Answer true if I am bound to my arguments."
  7885.  
  7886.     ^strength ~~ #unbound!
  7887.  
  7888. isInput
  7889.     "Normal constraints are not input constraints. An input constraint is one that depends on external state, such as the mouse, the keyboard, or a clock."
  7890.  
  7891.     ^false!
  7892.  
  7893. isRequired
  7894.     "Answer true if this constraint is a required constraint."
  7895.  
  7896.     ^strength sameAs: (Strength required)!
  7897.  
  7898. isSatisfied
  7899.     "Answer true if this constraint is satisfied in the current solution."
  7900.  
  7901.     ^whichMethod notNil!
  7902.  
  7903. isStay
  7904.     "Normal constraints are not stay constraints. Stay constraints are a subclass."
  7905.  
  7906.     ^false!
  7907.  
  7908. isStrongerThan: aConstraint
  7909.     "Answer true if I am stronger than the given constraint."
  7910.  
  7911.     ^self strength stronger: aConstraint strength!
  7912.  
  7913. shouldUseGiven: stayOptimizationFlag
  7914.     "Answer true if this constraint should be added to the plan."
  7915.  
  7916.     ^(self doesSomething) and:        "use this constraint if it does something AND"
  7917.         [(stayOptimizationFlag not) or:            "(we aren't optimizing stays OR"
  7918.         [(whichMethod outputsAreStayIn: thingDatas) not]]    " the outputs are not all stay)"! !
  7919.  
  7920. !Constraint methodsFor: 'set constraints'!
  7921.  
  7922. partlyBind: incompleteRefs
  7923.     "To be used for Set Constraints. Partly bind myself to the given set of incomplete references. The references are incomplete because their root Things have not yet been filled in. The constraint will remain unbound but it will contain the given incomplete references. Warning: these references will not get copied by the clone operation."
  7924.  
  7925.     self isBound
  7926.         ifTrue: [self notify: 'This constraint is already bound!!'].
  7927.     variables _ incompleteRefs.
  7928.     thingDatas _ Array new: variables size.! !
  7929.  
  7930. !Constraint methodsFor: 'cloning'!
  7931.  
  7932. clone
  7933.     "Answer a copy of this constraint."
  7934.  
  7935.     ^self cloneUsing: IdentityDictionary new!
  7936.  
  7937. cloneMethods: cloneDictionary 
  7938.     "Update my methods using the mapping given by cloneDictionary."
  7939.  
  7940.     | newMethods newMethod |
  7941.     newMethods _ methods collect:
  7942.         [: m |
  7943.          newMethod _ m cloneWith: cloneDictionary for: self.
  7944.          (whichMethod == m) ifTrue: [whichMethod _ newMethod].
  7945.          newMethod].
  7946.     (newMethods ~= methods) ifTrue:
  7947.         [methods _ newMethods].!
  7948.  
  7949. cloneUsing: cloneDictionary 
  7950.     "Make a clone of myself using the mapping given by cloneDictionary."
  7951.  
  7952.     | myClone |
  7953.     myClone _ self shallowCopy.
  7954.     myClone cloneVariables: cloneDictionary.
  7955.     myClone cloneMethods: cloneDictionary.
  7956.     ^myClone!
  7957.  
  7958. cloneVariables: cloneDictionary 
  7959.     "Update my variables using the mapping given by cloneDictionary."
  7960.  
  7961.     self isBound
  7962.         ifTrue:
  7963.             [self variables:
  7964.                 (variables collect:
  7965.                     [: ref | ref cloneUsing: cloneDictionary])]
  7966.         ifFalse:
  7967.             [variables _ Array new: variables size].! !
  7968.  
  7969. !Constraint methodsFor: 'printing'!
  7970.  
  7971. definitionString
  7972.     "Answer a string containing my definition for the constraint definer."
  7973.  
  7974.     | out |
  7975.     out _ (String new: 200) writeStream.
  7976.     symbols with: variables do:
  7977.         [: sym : var |
  7978.          out tab; nextPutAll: sym, ': '.
  7979.          (var root isThing)
  7980.             ifTrue: [out nextPutAll: 'THING']
  7981.             ifFalse: [var root printOn: out].
  7982.          out nextPutAll: '.', var longName.
  7983.          out cr].
  7984.     out cr.
  7985.     methods do:
  7986.         [: method |
  7987.          out nextPutAll: method codeString; cr; cr].
  7988.     ^out contents!
  7989.  
  7990. longPrintOn: aStream
  7991.  
  7992.     | bindings |
  7993.     aStream nextPut: $(.
  7994.     self shortPrintOn: aStream.
  7995.     aStream cr; nextPutAll: self strength printString, ', '.
  7996.     aStream nextPutAll:
  7997.         ((self isSatisfied) ifTrue: ['SAT'] ifFalse: ['NOT SAT']).
  7998.     bindings _ (self isSatisfied)
  7999.         ifTrue: [whichMethod bindings]
  8000.         ifFalse: [String new: variables size withAll: $X].
  8001.     variables with: bindings do: [: v : binding |
  8002.         aStream cr; tab.
  8003.         aStream nextPut: binding; space.
  8004.         v printOn: aStream.
  8005.         (v thingData isNil)
  8006.             ifTrue: [aStream nextPutAll: ' nil']
  8007.             ifFalse:
  8008.                 [aStream nextPutAll:
  8009.                     ' TD(', v thingData asOop printString, ') '.
  8010.                  v thingData walkStrength printOn: aStream]].
  8011.     aStream nextPut: $).!
  8012.  
  8013. printOn: aStream
  8014.  
  8015.     (Sensor leftShiftDown)
  8016.         ifTrue: [self longPrintOn: aStream]
  8017.         ifFalse: [self shortPrintOn: aStream].!
  8018.  
  8019. shortPrintOn: aStream
  8020.  
  8021.     aStream nextPutAll: self class name, '(', self asOop printString, ')'.! !
  8022. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  8023.  
  8024. Constraint class
  8025.     instanceVariableNames: ''!
  8026.  
  8027.  
  8028. !Constraint class methodsFor: 'instance creation'!
  8029.  
  8030. symbols: symbols equation: equation
  8031.     "Similar to symbols:equation:refs:strength: but the constraint is not bound to references at this time."
  8032.  
  8033.     | methodList |
  8034.     methodList _ (EquationTranslator methodsFor: equation) collect:
  8035.         [: m | Method symbols: symbols methodString: m].
  8036.     ^(super new)
  8037.         symbols: symbols
  8038.         methods: methodList!
  8039.  
  8040. symbols: symbols equation: equation refs: refs strength: strength
  8041.     "Create and initialize a new constraint using the given Smalltalk expression as an equation. The equation should be of the form '(expr1) = (expr2)'. For example, the following builds a Sum constraint with methods to solve for any one variable in terms of the remaining two:
  8042.     Constraint
  8043.         symbols: #(a b c)
  8044.         equation: 'c = (a + b)'
  8045.         refs: (Array
  8046.             with: aThing->#a.value
  8047.             with: aThing->#b.value
  8048.             with: aThing->#c.value
  8049.         strength: #required"
  8050.  
  8051.     | methodList |
  8052.     methodList _ (EquationTranslator methodsFor: equation) collect:
  8053.         [: m | Method symbols: symbols methodString: m].
  8054.     ^((super new)
  8055.         symbols: symbols
  8056.         methods: methodList)
  8057.             bind: refs strength: strength!
  8058.  
  8059. symbols: symbolList methods: methodList
  8060.     "Answer a new instance with the given methods. The instance is initially unbound."
  8061.  
  8062.     ^(super new)
  8063.         symbols: symbolList
  8064.         methods: methodList!
  8065.  
  8066. symbols: symbols methodStrings: methodStrings
  8067.     "Similar to symbols:methodStrings:refs:strength: but the constraint is not bound to references at this time."
  8068.  
  8069.     | methodList |
  8070.     methodList _ methodStrings collect:
  8071.         [: m | Method symbols: symbols methodString: m].
  8072.     ^(super new)
  8073.         symbols: symbols
  8074.         methods: methodList!
  8075.  
  8076. symbols: symbols methodStrings: methodStrings refs: refs strength: strength
  8077.     "Create and initialize a new constraint using the given method strings. The expressions in methodStrings are compiled to produce the actual method bodies for the constraint. For example, the following builds a one-way constraint that computes the magnitude of a vector:
  8078.     Constraint
  8079.         symbols: #(magnitude vector)
  8080.         methodStrings: #('magnitude _ (vector dotProduct: vector) sqrt')
  8081.         refs: (Array
  8082.             with: aThing->#tension
  8083.             with: aThing->#forceVector)
  8084.         strength: #required"
  8085.  
  8086.     | methodList |
  8087.     methodList _ methodStrings collect:
  8088.         [: m | Method symbols: symbols methodString: m].
  8089.     ^((super new)
  8090.         symbols: symbols
  8091.         methods: methodList)
  8092.             bind: refs strength: strength! !
  8093.  
  8094. Controller subclass: #GestureController
  8095.     instanceVariableNames: 'startTime '
  8096.     classVariableNames: ''
  8097.     poolDictionaries: ''
  8098.     category: 'ThingLabII-UI-Framework'!
  8099. GestureController comment:
  8100. 'This class supports simple multiple-click and drag gestures. It uses the passage of time to determine the difference between a click, double-click, or drag gesture.'!
  8101.  
  8102.  
  8103. !GestureController methodsFor: 'control defaults'!
  8104.  
  8105. controlActivity
  8106.     "Process user activity. This consists of either red button gestures or yellow button menu activity. Any other activity is handled by my superclass. Examples of gestures are: click, double-click, drag, and sweep (a special kind of drag). See the 'gestures' category for the full list."
  8107.  
  8108.     (sensor yellowButtonPressed) ifTrue: [^self menuActivity].
  8109.     (sensor redButtonPressed) ifTrue: [^self possibleClickAt: sensor cursorPoint].
  8110.     super controlActivity.!
  8111.  
  8112. isControlActive
  8113.     "Let the super view handle blue button activity."
  8114.  
  8115.     ^self viewHasCursor & sensor blueButtonPressed not! !
  8116.  
  8117. !GestureController methodsFor: 'gestures'!
  8118.  
  8119. clickAt: aPoint
  8120.     "Perform action for a red button click at the given point. The default is to do vanilla red button activity."
  8121.  
  8122.     self redButtonActivity.!
  8123.  
  8124. doubleClickAt: aPoint
  8125.     "Perform action for a red button double-click at the given point. The default is to do vanilla red button activity."
  8126.  
  8127.     self redButtonActivity.!
  8128.  
  8129. dragAt: aPoint
  8130.     "Perform action for a red button drag starting at the given point. The default is to do vanilla red button activity."
  8131.  
  8132.     self redButtonActivity.!
  8133.  
  8134. redButtonActivity
  8135.     "If the subclass does not override a gesture messages, it is sent this message to perform vanilla red button activity. This default method does nothing."!
  8136.  
  8137. sweepAt: aPoint
  8138.     "Perform action for a red button sweep starting at the given point. (A sweep is a diagonal down-and-right drag, used by some applications to sweep out an area for group selection.) The default is to do vanilla red button activity."
  8139.  
  8140.     self redButtonActivity.! !
  8141.  
  8142. !GestureController methodsFor: 'menu support'!
  8143.  
  8144. menuActivity
  8145.     "If the yellow button is pressed, this message is sent to the controller to handle the application menu. It is up to subclasses to override this message. This default method does nothing."! !
  8146.  
  8147. !GestureController methodsFor: 'private-timer'!
  8148.  
  8149. resetTimer
  8150.     "Reset our timer by remembering the current value of the millisecond clock."
  8151.  
  8152.     startTime _ Time millisecondClockValue.!
  8153.  
  8154. timeOut: timeOutInMilliseconds
  8155.     "Compute the timer value by subtracting the time at which the timer was last reset from the current millisecond clock value. Answer true if the result is greater than timeOutInMilliseconds."
  8156.  
  8157.     | timerVal |
  8158.     timerVal _ Time millisecondClockValue - startTime.
  8159.     ^(timerVal > timeOutInMilliseconds)! !
  8160.  
  8161. !GestureController methodsFor: 'private-gestures'!
  8162.  
  8163. dragOrSweepAt: aPoint
  8164.     "The button was held down too long for it to be a click so it is either a drag or a sweep. It is considered a sweep if the mouse has moved in definite downward-and-right manner between the time the button was depressed and now. (Note that the constants in this method may need to be changed if the timeout in possibleClickAt: is changed.)"
  8165.  
  8166.     | delta |
  8167.     delta _ sensor cursorPoint - aPoint.
  8168.     ((delta x > 1) & (delta y > 1))
  8169.         ifTrue: [self sweepAt: aPoint]
  8170.         ifFalse: [self dragAt: aPoint].!
  8171.  
  8172. possibleClickAt: aPoint
  8173.     "Invoked when the red button is first depressed. If the button is released before the timeout period has elapsed, then there is at least one click and we must look for a second click. Otherwise, the gesture is a drag or sweep." 
  8174.  
  8175.     self resetTimer.
  8176.     [(self timeOut: 150) not & sensor redButtonPressed]
  8177.         whileTrue: ["wait for timeout or button up"].
  8178.     (sensor redButtonPressed not)    "has the button gone up?"
  8179.         ifTrue: [self possibleDoubleClickAt: aPoint]
  8180.         ifFalse: [self dragOrSweepAt: aPoint].!
  8181.  
  8182. possibleDoubleClickAt: aPoint
  8183.     "Invoked after the first click (i.e. the button is up). If the button is depressed again before the timeout period has elapsed, then the gesture is a double click. Otherwise, the gesture is a single click. A single click is recorded immediately. Thus, a double click causes the sequence of messages: 'clickAt:' and 'doubleClickAt:' to be sent."
  8184.  
  8185.     self resetTimer.
  8186.     [(self timeOut: 260) not & sensor redButtonPressed not]
  8187.         whileTrue: ["wait for timeout or button down"].
  8188.     (sensor redButtonPressed)    "has the button gone down?"
  8189.         ifTrue: [self doubleClickAt: aPoint]
  8190.         ifFalse: [self clickAt: aPoint].! !
  8191.  
  8192. SceneView subclass: #BasicThingView
  8193.     instanceVariableNames: ''
  8194.     classVariableNames: ''
  8195.     poolDictionaries: ''
  8196.     category: 'ThingLabII-UI-Thing Views'!
  8197. BasicThingView comment:
  8198. 'A BasicThingView is used to display a Thing under construction. A ThingAdaptor is the model and a ThingConstructorController is the controller. When the user edits or moves some part of the thing under construction, this class computes the parts of the display that stay the same so that only the parts that are changing need be redisplayed. This class is also responsible for accepting new Things when they are are dragging into it from a PartsBin.'!
  8199.  
  8200.  
  8201. !BasicThingView methodsFor: 'controller access'!
  8202.  
  8203. defaultControllerClass
  8204.  
  8205.     ^BasicThingController! !
  8206. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  8207.  
  8208. BasicThingView class
  8209.     instanceVariableNames: ''!
  8210.  
  8211.  
  8212. !BasicThingView class methodsFor: 'instance creation'!
  8213.  
  8214. on: aThing
  8215.     "Create a new view on the given Thing."
  8216.  
  8217.     ^self new model: (ThingAdaptor on: aThing)!
  8218.  
  8219. openOn: aThing
  8220.     "Open a view on the given Thing."
  8221.  
  8222.     self
  8223.         openWithSubview: (self on: aThing)
  8224.         label: (aThing name).!
  8225.  
  8226. openOn: aThing from: aPartHolder zoomingFrom: fromRect to: openFrame
  8227.     "Open a view on the given Thing zooming from fromRect to openFrame. Remember that this view was opened from the given partHolder."
  8228.  
  8229.     self
  8230.         openWithSubview: (self on: aThing)
  8231.         label: (aThing name)
  8232.         fromHolder: aPartHolder
  8233.         zoomFrom: fromRect 
  8234.         to: openFrame.! !
  8235.  
  8236. AbstractMethod subclass: #Method
  8237.     instanceVariableNames: 'block '
  8238.     classVariableNames: ''
  8239.     poolDictionaries: ''
  8240.     category: 'ThingLabII-Constraints'!
  8241. Method comment:
  8242. 'I represent a normal (i.e. non-module) method.
  8243. Instance variables are (in addition to those inherited):
  8244.  
  8245.     block...    block to execute to enforce the constraint <BlockContext>
  8246.  
  8247. '!
  8248.  
  8249.  
  8250. !Method methodsFor: 'initialize-release'!
  8251.  
  8252. block: aBlock
  8253.     "Set my code block. Used to initialize special constraints."
  8254.  
  8255.     block _ aBlock.!
  8256.  
  8257. destroy
  8258.     "Break potential cycles."
  8259.  
  8260.     block _ nil.
  8261.     super destroy.!
  8262.  
  8263. symbols: symbols methodString: methodString
  8264.     "Initialize a method by compiling the given string considering the given collection of symbols to represent the parameters of the method (i.e. its inputs and outputs). A given variable may not be both an input and an output. Note: Free variables in the methodString will be handled as they are for any block, however the user is given a warning, since free variables in a constraint methods are unusual and may indicate a programmer error."
  8265.  
  8266.     | insOutsTemps ins outs temps |
  8267.     insOutsTemps _ self extractInsOutsAndTemps: methodString using: symbols.
  8268.     ins _ insOutsTemps at: 1.
  8269.     outs _ insOutsTemps at: 2.
  8270.     temps _ insOutsTemps at: 3.
  8271.     self checkIns: ins outs: outs temps: temps all: symbols.
  8272.     codeString _ methodString.
  8273.     bindings _ self makeBindingArrayForIns: ins outs: outs varVector: symbols.
  8274.     block _ Compiler
  8275.             evaluate:
  8276.                 ((self blockPrefixForIns: ins temps: temps args: symbols),
  8277.                  methodString,
  8278.                  (self blockPostfixForOuts: outs allNames: symbols))
  8279.             for: nil
  8280.             logged: false.
  8281.     (temps size > 0) ifTrue: [block fixTemps].! !
  8282.  
  8283. !Method methodsFor: 'DeltaBlue'!
  8284.  
  8285. execute: refList
  8286.     "Execute myself to enforce my constraint. refList contains all the References for my constraint."
  8287.  
  8288.     block value: refList.! !
  8289.  
  8290. !Method methodsFor: 'private'!
  8291.  
  8292. blockPostfixForOuts: outNames allNames: allNames
  8293.     "Answer a string to be used as the postfix when creating a block for this method. All output temporary variables are stored via their References in the argument array and the block is terminated."
  8294.  
  8295.     | stream |
  8296.     "make a stream and add separator to terminate user's method string"
  8297.     stream _ WriteStream on: (String new).
  8298.     stream nextPutAll: '.'; cr.
  8299.  
  8300.     "build the expression postfix, creating assignments for all outputs"
  8301.     1 to: allNames size do:
  8302.         [: index |
  8303.          (outNames includes: (allNames at: index)) ifTrue:
  8304.             [stream tab; nextPutAll: '(vars at: '.
  8305.              stream nextPutAll: index printString, ') value: '.
  8306.              stream nextPutAll: (allNames at: index), '.'; cr]].
  8307.  
  8308.     "nil out all temps, to avoid keeping pointers to garbage"
  8309.     allNames do:
  8310.         [: name |
  8311.          stream tab; nextPutAll: name, ' _ nil.'; cr].
  8312.     stream tab; nextPutAll: 'vars _ nil]'; cr.
  8313.  
  8314.     ^stream contents!
  8315.  
  8316. blockPrefixForIns: inNames temps: tempNames args: argNames
  8317.     "Answer a string to be used as the prefix when creating a block for a method with the given input names. All constraint variables are declared as temporaries, in addition to the temporary variables from the method string. Input variable temporaries are initialized from the argument vector."
  8318.  
  8319.     | stream |
  8320.     stream _ WriteStream on: (String new).
  8321.  
  8322.     "build the expression prefix, making all the variables look like temps"
  8323.     stream nextPutAll: '| vars '.
  8324.     argNames do: [: v | stream nextPutAll: v; space].
  8325.     tempNames do: [: v | stream nextPutAll: v; space].
  8326.     stream nextPutAll: '|'; cr.
  8327.  
  8328.     "build the block header and input assignments"
  8329.     stream tab; nextPutAll: '[: vars |'; cr.
  8330.     1 to: argNames size do:
  8331.         [: index |
  8332.          (inNames includes: (argNames at: index)) ifTrue:
  8333.             [stream tab; nextPutAll: (argNames at: index), ' _ (vars at: '.
  8334.             stream nextPutAll: index printString.
  8335.             stream nextPutAll: ') value.'; cr]].
  8336.  
  8337.     stream tab.
  8338.     ^stream contents!
  8339.  
  8340. checkIns: inNames outs: outNames temps: tempNames all: allNames
  8341.     "Notify the user and answer nil if the input and output arg lists are not disjoint. Warn the user if the method code has free variables (these will be made into temporaries)."
  8342.  
  8343.     outNames do:
  8344.         [: v |
  8345.          ((inNames includes: v) and:
  8346.           [allNames includes: v]) ifTrue:
  8347.             [self error: v asString, ' cannot be both input and output!!']].
  8348.  
  8349.     tempNames do:
  8350.         [: v |
  8351.          Transcript show:
  8352.             'Warning: ''', v, ''' is assumed to be a temporary.'; cr].!
  8353.  
  8354. extractInsOutsAndTemps: methodString using: allNames
  8355.     "Extract the input, output and temporary variable names from the Smalltalk expression represented by the given string. A temporary variable is one that is neither an input, an output, or a global. Answer an array containing the three lists (ins, outs, temps)."
  8356.  
  8357.     | parseTree ins outs temps |
  8358.     parseTree _ EquationParser parse: ('DoIt ', methodString) readStream.
  8359.     ins _ parseTree referenced.
  8360.     outs _ parseTree assignedTo.
  8361.     temps _ parseTree allVariables select:
  8362.         [: v | ((allNames includes: v) not) &
  8363.               ((Smalltalk includesKey: v) not)].
  8364.     ^Array with: ins with: outs with: temps!
  8365.  
  8366. makeBindingArrayForIns: inNames outs: outNames varVector: constraintArgs
  8367.     "Compute and answer the bindings array for the given sets of variable names. The bindings array contains for each symbol in the constraint arguments vector:
  8368.         $i if the variable is an input
  8369.         $o if the variable is an output
  8370.         $x if the variable is not referenced by this method"
  8371.  
  8372.     ^(constraintArgs collect:
  8373.         [: varName |
  8374.          (inNames includes: varName)
  8375.             ifTrue: [$i]
  8376.             ifFalse:
  8377.                 [(outNames includes: varName)
  8378.                     ifTrue: [$o]
  8379.                     ifFalse: [$x]]]) asArray! !
  8380. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  8381.  
  8382. Method class
  8383.     instanceVariableNames: ''!
  8384.  
  8385.  
  8386. !Method class methodsFor: 'instance creation'!
  8387.  
  8388. symbols: symbols methodString: methodString
  8389.     "Answer a new, initialized instance."
  8390.  
  8391.     ^(super new)
  8392.         symbols: symbols methodString: methodString! !
  8393.  
  8394. Object subclass: #ClippingRectangle
  8395.     instanceVariableNames: 'xMin xMax yMin yMax u0 u1 '
  8396.     classVariableNames: ''
  8397.     poolDictionaries: ''
  8398.     category: 'ThingLabII-UI-Support'!
  8399. ClippingRectangle comment:
  8400. 'I support line clipping using the standard algorithm (see, e.g., Foley and vanDam''s book on interactive graphics). If I have zero area (because my height or width is zero) then I will report that no lines intersect me.'!
  8401.  
  8402.  
  8403. !ClippingRectangle methodsFor: 'clipping'!
  8404.  
  8405. clipFrom: beginPoint to: endPoint
  8406.     "Clip the line (beginPoint, endPoint) and answer an array of three elements, (drawFlag, clippedBegin, clippedEnd). If the first element of the answer is false, the line is completely outside the clipping rectangle, and need not be displayed. If the first element of answer is true, the second two elements are the beginning and ending points of the clipped line."
  8407.  
  8408.     | beginX beginY dx dy clippedBegin clippedEnd |
  8409.     self noArea ifTrue: ["line rejected" ^Array with: false with: nil with: nil].
  8410.     u0 _ 0.0.
  8411.     u1 _ 1.0.
  8412.     beginX _ beginPoint x.
  8413.     beginY _ beginPoint y.
  8414.     dx _ endPoint x - beginX.
  8415.     dy _ endPoint y - beginY.
  8416.  
  8417.     ((self clip: (beginX - xMin) delta: dx negated) and:
  8418.      [(self clip: (xMax - beginX) delta: dx) and:
  8419.      [(self clip: (beginY - yMin) delta: dy negated) and:
  8420.      [(self clip: (yMax - beginY) delta: dy)]]])
  8421.         ifFalse: ["line rejected" ^Array with: false with: nil with: nil].
  8422.  
  8423.     "If we haven't rejected the line by now, some of it must lie within the clipping rectangle. If u0 or u1 are within the open interval (0..1), use them to compute the new line segment start and/or point."
  8424.     dx _ dx asFloat.
  8425.     dy _ dy asFloat.
  8426.     (u0 > 0.0)
  8427.         ifTrue: [clippedBegin _ beginPoint +
  8428.                 ((dx asFloat * u0)@(dy asFloat * u0)) rounded]
  8429.         ifFalse: [clippedBegin _ beginPoint].
  8430.     (u1 < 1.0)
  8431.         ifTrue: [clippedEnd _ beginPoint +
  8432.                 ((dx asFloat * u1)@(dy asFloat * u1)) rounded]
  8433.         ifFalse: [clippedEnd _ endPoint].
  8434.     ^Array with: true with: clippedBegin with: clippedEnd!
  8435.  
  8436. noArea
  8437.     "Answer true if either my width or my height are zero."
  8438.  
  8439.     ^(xMin == xMax) | (yMin == yMax)! !
  8440.  
  8441. !ClippingRectangle methodsFor: 'private'!
  8442.  
  8443. clip: e delta: d
  8444.  
  8445.     | r |
  8446.     "Case 1: line parallel to boundary"
  8447.     (d = 0) ifTrue: [^e >= 0].        "accept if e is on boundary or inside"
  8448.  
  8449.     r _ e asFloat / d asFloat.        "the normalized intersection with the boundary"
  8450.     "Case 2: line from outside to inside"
  8451.     (d < 0) ifTrue:
  8452.         [(r > u1) ifTrue: [^false].        "reject"
  8453.          u0 _ u0 max: r.                "update u0 and accept"
  8454.          ^true].
  8455.     "Case 3: line from inside to outside"
  8456.     (d > 0) ifTrue:
  8457.         [(r < u0) ifTrue: [^false].        "reject"
  8458.          u1 _ u1 min: r.                "update u1 and accept"
  8459.          ^true].!
  8460.  
  8461. clipOrigin: origin corner: corner
  8462.     "This is the initialization message. corner should be >= origin, but if it isn't you will simply get an empty clipping rectangle."
  8463.  
  8464.     xMin _ origin x.
  8465.     yMin _ origin y.
  8466.     xMax _ xMin max: corner x.
  8467.     yMax _ yMin max: corner y.! !
  8468. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  8469.  
  8470. ClippingRectangle class
  8471.     instanceVariableNames: ''!
  8472.  
  8473.  
  8474. !ClippingRectangle class methodsFor: 'instance creation'!
  8475.  
  8476. from: aRectangle
  8477.  
  8478.     ^(self new)
  8479.         clipOrigin: aRectangle origin corner: aRectangle corner!
  8480.  
  8481. origin: point1 corner: point2
  8482.  
  8483.     ^(self new)
  8484.         clipOrigin: point1 corner: point2!
  8485.  
  8486. origin: point1 extent: extent
  8487.  
  8488.     ^(self new)
  8489.         clipOrigin: point1 corner: (point1 + extent)! !
  8490.  
  8491. !ClippingRectangle class methodsFor: 'example'!
  8492.  
  8493. example1
  8494.     "ClippingRectangle example1"
  8495.  
  8496.     | r ans |
  8497.     r _ ClippingRectangle origin: 0@0 corner: 20@20.
  8498.     ans _ r clipFrom: -5@-5 to: 32@32.
  8499.     ^(ans first)
  8500.         ifFalse: ['REJECTED']
  8501.         ifTrue: [(ans at: 2) printString,
  8502.                 ' -> ', (ans at: 3) printString]!
  8503.  
  8504. example2
  8505.     "ClippingRectangle example2"
  8506.  
  8507.     | r lines ans |
  8508.     r _ ClippingRectangle origin: 0@0 corner: 20@20.
  8509.     lines _ (OrderedCollection new)
  8510.         "these should be accepted and possibly clipped"
  8511.         add: (Array with: 5@5 with: 32@32);
  8512.         add: (Array with: -5@-5 with: 12@12);
  8513.         add: (Array with: 32@32 with: -5@-5);
  8514.         add: (Array with: 5@5 with: 12@12);
  8515.  
  8516.         "these should be rejected"
  8517.         add: (Array with: -5@-5 with: -5@132);
  8518.         add: (Array with: -5@-5 with: -112@-112);
  8519.         add: (Array with: 32@32 with: 70@90);
  8520.         add: (Array with: 32@5 with: 70@5);
  8521.         add: (Array with: -5@5 with: -1@5);
  8522.         add: (Array with: -5@-5 with: -1@12);
  8523.         yourself.
  8524.     ^lines collect: [: l |
  8525.         ans _ r clipFrom: (l at: 1) to: (l at: 2).
  8526.         (l at: 1) printString, ' -> ', (l at: 2) printString, ' ==> ',
  8527.             ((ans first)
  8528.                 ifFalse: ['REJECTED']
  8529.                 ifTrue: [(ans at: 2) printString, ' -> ', (ans at: 3) printString])]! !
  8530.  
  8531. Object subclass: #BusyCursor
  8532.     instanceVariableNames: ''
  8533.     classVariableNames: ''
  8534.     poolDictionaries: ''
  8535.     category: 'ThingLabII-UI-Support'!
  8536. BusyCursor comment:
  8537. 'This is a single-instance class implemented in the class protocol that implements animated busy cursors. Several variations are supported.'!
  8538.  
  8539. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  8540.  
  8541. BusyCursor class
  8542.     instanceVariableNames: 'current cursors oldCursor '!
  8543.  
  8544.  
  8545. !BusyCursor class methodsFor: 'class initialization'!
  8546.  
  8547. initialize
  8548.     "BusyCursor initialize."
  8549.  
  8550.     self initialize1.!
  8551.  
  8552. initialize1
  8553.     "Spinning smiley face."
  8554.     "BusyCursor initialize1."
  8555.  
  8556.     current _ 1.
  8557.     cursors _ Array new: 8.
  8558.     cursors at: 1 put: (Cursor
  8559.     extent: 16@16
  8560.     fromArray: #( 0 1984 6192 8200 16388 19556 35938 32770 32770 36882 38962 20452 18372 8200 6192 1984)
  8561.     offset: 0@0).
  8562.     cursors at: 8 put: (Cursor
  8563.     extent: 16@16
  8564.     fromArray: #( 0 1984 6192 8200 16772 16772 32786 32786 38930 38962 32882 16612 18372 8200 6192 1984)
  8565.     offset: 0@0).
  8566.     cursors at: 7 put: (Cursor
  8567.     extent: 16@16
  8568.     fromArray: #( 0 1984 6192 8200 16580 19556 35890 32818 32818 32818 35890 19556 16580 8200 6192 1984)
  8569.     offset: 0@0).
  8570.     cursors at: 6 put: (Cursor
  8571.     extent: 16@16
  8572.     fromArray: #( 0 1984 6192 8200 17348 16612 32882 38962 38930 32786 32786 16772 16772 8200 6192 1984)
  8573.     offset: 0@0).
  8574.     cursors at: 5 put: (Cursor
  8575.     extent: 16@16
  8576.     fromArray: #( 0 1984 6192 8200 18372 20452 38962 36882 32770 32770 35938 19556 16388 8200 6192 1984)
  8577.     offset: 0@0).
  8578.     cursors at: 4 put: (Cursor
  8579.     extent: 16@16
  8580.     fromArray: #( 0 1984 6192 8200 18372 19972 39938 38962 36914 36866 36866 16772 16772 8200 6192 1984)
  8581.     offset: 0@0).
  8582.     cursors at: 3 put: (Cursor
  8583.     extent: 16@16
  8584.     fromArray: #( 0 1984 6192 8200 17924 19556 39010 38914 38914 38914 39010 19556 17924 8200 6192 1984)
  8585.     offset: 0@0).
  8586.     cursors at: 2 put: (Cursor
  8587.     extent: 16@16
  8588.     fromArray: #( 0 1984 6192 8200 17156 17156 36866 36866 36914 38962 39938 19972 18372 8200 6192 1984)
  8589.     offset: 0@0).
  8590.     self example: 40.!
  8591.  
  8592. initialize2
  8593.     "Spinning slice of pie."
  8594.     "BusyCursor initialize2."
  8595.  
  8596.     current _ 1.
  8597.     cursors _ Array new: 8.
  8598.     cursors at: 1 put: (Cursor
  8599.     extent: 16@16
  8600.     fromArray: #( 0 1984 6640 8696 16892 16892 33278 33278 33278 32770 32770 16388 16388 8200 6192 1984)
  8601.     offset: 0@0).
  8602.     cursors at: 2 put: (Cursor
  8603.     extent: 16@16
  8604.     fromArray: #( 0 1984 6192 8200 16412 16444 32894 33022 33278 33022 32894 16444 16412 8200 6192 1984)
  8605.     offset: 0@0).
  8606.     cursors at: 3 put: (Cursor
  8607.     extent: 16@16
  8608.     fromArray: #( 0 1984 6192 8200 16388 16388 32770 32770 33278 33278 33278 16892 16892 8696 6640 1984)
  8609.     offset: 0@0).
  8610.     cursors at: 4 put: (Cursor
  8611.     extent: 16@16
  8612.     fromArray: #( 0 1984 6192 8200 16388 16388 32770 32770 33026 33666 34754 20452 24564 16376 8176 1984)
  8613.     offset: 0@0).
  8614.     cursors at: 5 put: (Cursor
  8615.     extent: 16@16
  8616.     fromArray: #( 0 1984 6192 8200 16388 16388 32770 32770 65282 65282 65282 32516 32516 16136 7984 1984)
  8617.     offset: 0@0).
  8618.     cursors at: 6 put: (Cursor
  8619.     extent: 16@16
  8620.     fromArray: #( 0 1984 6192 8200 28676 30724 64514 65026 65282 65026 64514 30724 28676 8200 6192 1984)
  8621.     offset: 0@0).
  8622.     cursors at: 7 put: (Cursor
  8623.     extent: 16@16
  8624.     fromArray: #( 0 1984 7984 16136 32516 32516 65282 65282 65282 32770 32770 16388 16388 8200 6192 1984)
  8625.     offset: 0@0).
  8626.     cursors at: 8 put: (Cursor
  8627.     extent: 16@16
  8628.     fromArray: #( 0 1984 8176 16376 24564 20452 34754 33666 33026 32770 32770 16388 16388 8200 6192 1984)
  8629.     offset: 0@0).
  8630.     self example: 40.!
  8631.  
  8632. initialize3
  8633.     "Beanie with spinning propeller."
  8634.     "BusyCursor initialize3."
  8635.  
  8636.     current _ 1.
  8637.     cursors _ Array new: 6.
  8638.     "horizontal"
  8639.     cursors at: 1 put: (Cursor
  8640.         extent: 16@16
  8641.         fromArray: #(0 0 14 32766 29056 384 384 384 8184 30702 52275 38937 65535 0 0 0)
  8642.         offset: 0@0).
  8643.     "uphill"
  8644.     cursors at: 2 put: (Cursor
  8645.         extent: 16@16
  8646.         fromArray: #(0 14 62 480 1920 32128 29056 384 8184 30702 52275 38937 65535 0 0 0)
  8647.         offset: 0@0).
  8648.     "steep uphill"
  8649.     cursors at: 3 put: (Cursor
  8650.         extent: 16@16
  8651.         fromArray: #(112 112 64 128 384 896 3968 3968 8184 30702 52275 38937 65535 0 0 0)
  8652.         offset: 0@0).
  8653.     "vertical"
  8654.     cursors at: 4 put: (Cursor
  8655.         extent: 16@16
  8656.         fromArray: #(0 0 384 384 384 384 384 384 8184 30702 52659 39321 65535 0 0 0)
  8657.         offset: 0@0).
  8658.     "steep downhill"
  8659.     cursors at: 5 put: (Cursor
  8660.         extent: 16@16
  8661.         fromArray: #(7168 7168 1536 768 384 448 496 496 8184 30702 52275 38937 65535 0 0 0)
  8662.         offset: 0@0).
  8663.     "downhill"
  8664.     cursors at: 6 put: (Cursor
  8665.         extent: 16@16
  8666.         fromArray: #(0 0 31744 30592 494 446 384 384 8184 30702 52275 38937 65535 0 0 0)
  8667.         offset: 0@0).
  8668.     self example: 40.!
  8669.  
  8670. initialize4
  8671.     "Spinning propeller."
  8672.     "BusyCursor initialize4."
  8673.  
  8674.     current _ 1.
  8675.     cursors _ Array new: 8.
  8676.     "horizontal"
  8677.     cursors at: 1 put: (Cursor
  8678.         extent: 16@16
  8679.         fromArray: #(0 0 0 0 0 0 0 956 32764 31616 0 0 0 0 0 0)
  8680.         offset: 0@0).
  8681.     "slantUp1"
  8682.     cursors at: 2 put: (Cursor
  8683.         extent: 16@16
  8684.         fromArray: #(0 0 0 0 0 12 60 1008 896 8064 30720 24576 0 0 0 0)
  8685.         offset: 0@0).
  8686.     "slantUp2"
  8687.     cursors at: 3 put: (Cursor
  8688.         extent: 16@16
  8689.         fromArray: #(0 0 0 12 28 56 112 896 896 896 7168 14336 28672 24576 0 0)
  8690.         offset: 0@0).
  8691.     "slantUp3"
  8692.     cursors at: 4 put: (Cursor
  8693.         extent: 16@16
  8694.         fromArray: #(0 0 96 96 192 192 128 896 896 896 512 1536 1536 3072 3072 0)
  8695.         offset: 0@0).
  8696.     "vertical"
  8697.     cursors at: 5 put: (Cursor
  8698.         extent: 16@16
  8699.         fromArray: #(0 0 768 768 768 768 256 896 896 896 256 384 384 384 384 0)
  8700.         offset: 0@0).
  8701.     "slantDown1"
  8702.     cursors at: 6 put: (Cursor
  8703.         extent: 16@16
  8704.         fromArray: #(0 0 3072 3072 1536 1536 512 896 896 896 128 192 192 96 96 0)
  8705.         offset: 0@0).
  8706.     "slantDown2"
  8707.     cursors at: 7 put: (Cursor
  8708.         extent: 16@16
  8709.         fromArray: #(0 0 0 24576 28672 14336 7168 896 896 896 112 56 28 12 0 0)
  8710.         offset: 0@0).
  8711.     "slantDown3"
  8712.     cursors at: 8 put: (Cursor
  8713.         extent: 16@16
  8714.         fromArray: #(0 0 0 0 0 24576 30720 8064 896 1008 60 12 0 0 0 0)
  8715.         offset: 0@0).
  8716.     self example: 40.! !
  8717.  
  8718. !BusyCursor class methodsFor: 'busy cursor'!
  8719.  
  8720. begin
  8721.     "Start showing the BusyCursor."
  8722.     oldCursor _ Cursor currentCursor.
  8723.     (cursors at: current) show!
  8724.  
  8725. dec
  8726.     "Decrement the BusyCursor."
  8727.     current _ current - 1.
  8728.     current < 1 ifTrue: [current _ cursors size].
  8729.     (cursors at: current) show!
  8730.  
  8731. end
  8732.     "End showing the BusyCursor."
  8733.     oldCursor show!
  8734.  
  8735. inc
  8736.     "Increment the BusyCursor."
  8737.     current _ current + 1.
  8738.     current > cursors size ifTrue: [current _ 1].
  8739.     (cursors at: current) show! !
  8740.  
  8741. !BusyCursor class methodsFor: 'example'!
  8742.  
  8743. example: aTime
  8744.     "BusyCursor example: 40."
  8745.  
  8746.     self begin.
  8747.     1 to: 20 do: [:i | self inc. (Delay forMilliseconds: aTime) wait].
  8748.     1 to: 20 do: [:i | self dec. (Delay forMilliseconds: aTime) wait].
  8749.     self end! !
  8750.  
  8751.  
  8752. Object subclass: #ModuleSolution
  8753.     instanceVariableNames: 'methods plan isPossibleEquation outWalkEqns dependencies '
  8754.     classVariableNames: ''
  8755.     poolDictionaries: ''
  8756.     category: 'ThingLabII-Module Compiler'!
  8757. ModuleSolution comment:
  8758. 'I record information about one solution during the Module compilation process. I will eventually become one method of a Module constraint.'!
  8759.  
  8760.  
  8761. !ModuleSolution methodsFor: 'initialize-release'!
  8762.  
  8763. methods: methodList
  8764.     "Initialize myself."
  8765.  
  8766.     methods _ methodList.
  8767.     plan _ nil.                "filled in later"
  8768.     isPossibleEquation _ nil.    "filled in later"
  8769.     outWalkEqns _ nil.        "filled in later"
  8770.     dependencies _ nil.        "filled in later"! !
  8771.  
  8772. !ModuleSolution methodsFor: 'access'!
  8773.  
  8774. dependencies: aModuleDependency
  8775.     "Record my input/output dependencies."
  8776.  
  8777.     dependencies _ aModuleDependency.!
  8778.  
  8779. isPossibleEquation: aModuleAND
  8780.     "Record my strength check equation."
  8781.  
  8782.     isPossibleEquation _ aModuleAND.!
  8783.  
  8784. methods
  8785.     "Answer the list of methods that comprise this solution."
  8786.  
  8787.     ^methods!
  8788.  
  8789. outWalkEqns: eqnList
  8790.     "Record the walkabout strength equations for my outputs. These are in the same order as my dependencies list."
  8791.  
  8792.     outWalkEqns _ eqnList.!
  8793.  
  8794. plan: aPlan
  8795.     "Record my plan. The order of methods in the plan is different from the order in my 'methods' instance variable; the methods in the plan correspond to the order of constraints in the partition's constraint list whereas the order of methods in the plan is the correct execution order. The plan also omits null methods from stay and edit constraints."
  8796.  
  8797.     plan _ aPlan.! !
  8798.  
  8799. !ModuleSolution methodsFor: 'method gen'!
  8800.  
  8801. methodFor: module namePrefix: prefix constraints: constraints externalVars: externalVars varTable: varTable
  8802.     "Compile the check, execute, and propagate methods for this solution and install them in module's class. Name them using given prefix string. Answer a new ModuleMethod for this solution."
  8803.  
  8804.     | codeString |
  8805.     codeString _ self codeStringAndVarsFor: constraints varTable: varTable.
  8806.     self
  8807.         compileExecuteIn: module class
  8808.         prefix: prefix
  8809.         codeString: codeString
  8810.         varTable: varTable.
  8811.     self compileIsPossibleIn: module class prefix: prefix.
  8812.     self compilePropagateIn: module class prefix: prefix.
  8813.     ^ModuleMethod
  8814.         module: module
  8815.         codeString: codeString
  8816.         bindings: (self buildBindingArray: externalVars)
  8817.         isPossible: prefix, 'isPossible'
  8818.         execute: prefix, 'execute'
  8819.         propagate: prefix, 'propagate'! !
  8820.  
  8821. !ModuleSolution methodsFor: 'private-method gen'!
  8822.  
  8823. appendStatementsOf: methodTree to: aStream
  8824.     "Append the statements of the given method parse tree to the given stream. Omit the final '^self' statement."
  8825.  
  8826.     | statements s |
  8827.     "get method statements and remove final '^self'"
  8828.     statements _ methodTree block statements.
  8829.     statements _ statements copyFrom: 1 to: (statements size - 1).
  8830.     "add statements to aStream"
  8831.     statements do:
  8832.         [: statement |
  8833.          s _ statement printString.
  8834.          s _ s copyFrom: 2 to: (s size - 1).    "remove {} brackets"
  8835.          aStream tab; nextPutAll: s; nextPut: $.; cr].!
  8836.  
  8837. buildBindingArray: constraintArgs
  8838.     "Construct the bindings array for this solution for use in a ModuleMethod, using the given vector of external variables. The bindings array contains for each variable in the constraint arguments vector:
  8839.         $i if the variable is an input
  8840.         $o if the variable is an output
  8841.         $x if the variable is not referenced by this method"
  8842.  
  8843.     | outVars inVars bindings |
  8844.     outVars _ Set new: 8.
  8845.     inVars _ Set new: 8.
  8846.     dependencies do:
  8847.         [: d |
  8848.          outVars add: d outVar.    
  8849.          inVars addAll: d dependsOn].
  8850.     bindings _ constraintArgs collect:
  8851.         [: var |
  8852.          (outVars includes: var)
  8853.             ifTrue: [$o]
  8854.             ifFalse: [(inVars includes: var)
  8855.                 ifTrue: [$i]
  8856.                 ifFalse: [$x]]].
  8857.     ^bindings asArray!
  8858.  
  8859. codeStringAndVarsFor: constraints varTable: varTable
  8860.     "Answer the code string and the referenced variable list for this solution. The code string is derived by concatenating all the statements of the non-nil methods of this solution in order."
  8861.     "Details: The varible references in each method are renamed by using the reference and symbol vectors of its constraint and the varMap dictionary to map all the constraint argument names to their corresponding variable names in this context. We also inline expand all constant references at this time."
  8862.  
  8863.     | stream varMap constraint parser tree |
  8864.     stream _ (String new: 1000) writeStream.
  8865.     varMap _ IdentityDictionary new: varTable size.
  8866.     varTable do: [: v | varMap at: v thingData put: v].
  8867.     plan do:
  8868.         [: method |
  8869.          constraint _ constraints detect: [: c | c methods includes: method].
  8870.          parser _ EquationParser new.
  8871.          tree _ parser parse: ('DoIt ', method codeString) readStream.
  8872.          tree _ self
  8873.             remapVars: tree
  8874.             for: constraint
  8875.             varMap: varMap
  8876.             encoder: parser encoder.
  8877.          self appendStatementsOf: tree to: stream].
  8878.     ^stream contents!
  8879.  
  8880. remapVars: parseTree for: constraint varMap: varMap encoder: encoder
  8881.     "Remap the variable reference in the given parseTree to use the local name and expand constant references. varMap is a dictionary mapping thingDatas to ModuleVarTableEntries."
  8882.     "Details: First we construct a dictionary mapping the constraint's symbolic variable names to local names or constant expressions. Then we apply this mapping to the given parse tree."
  8883.  
  8884.     | mappingDict varEntry newName |
  8885.     mappingDict _ Dictionary new.
  8886.     constraint variables with: constraint symbols do:
  8887.         [: var : symbol |
  8888.          varEntry _ varMap at: var thingData.
  8889.          mappingDict at: symbol put:
  8890.             ((varEntry isConstant)
  8891.                 ifTrue: [varEntry literalTreeForUsing: encoder]
  8892.                 ifFalse: [encoder autoBind: varEntry name])].
  8893.     ^parseTree transformBy:    "apply the mapping"
  8894.         [: node |
  8895.          (node isMemberOf: VariableNode)
  8896.             ifTrue: [mappingDict at: (node name asSymbol) ifAbsent: [node]]
  8897.             ifFalse: [node]]! !
  8898.  
  8899. !ModuleSolution methodsFor: 'private-compilation'!
  8900.  
  8901. ancestorsAndStayCodeOn: aStream
  8902.     "Append onto the given stream code to propagate ancestors and stay values for this solution."
  8903.  
  8904.     | fixed nonFixed |
  8905.     aStream cr; cr; tab; nextPutAll: '| ins |'; cr.
  8906.     fixed _ dependencies select: [: entry | entry stay & entry dependsOn isEmpty].
  8907.     nonFixed _ dependencies select: [: entry | (fixed includes: entry) not].
  8908.  
  8909.     "output code to compute the DeltaBlue data for the outputs determined by stay constraints"
  8910.     fixed do:
  8911.         [: entry |
  8912.          aStream tab.
  8913.          entry outVar thingDataCodeStringOn: aStream.
  8914.          aStream tab; tab; nextPutAll: 'walkStrength: ', entry strengthString, ';'; cr.
  8915.          aStream tab; tab; nextPutAll: 'stay: true;'; cr.
  8916.          aStream tab; tab; nextPutAll: 'ancestors: #().'; cr].
  8917.  
  8918.     "output code to compute the ancestor and stay data for the outputs NOT determined by stay constraints"
  8919.     (nonFixed isEmpty) ifFalse:
  8920.         [nonFixed do:
  8921.             [: entry |
  8922.              aStream tab; nextPutAll: 'ins _ OrderedCollection new.'; cr.
  8923.              entry dependsOn do:
  8924.                 [: v |
  8925.                  aStream tab; nextPutAll: 'ins add: '.
  8926.                  v thingDataCodeStringOn: aStream.
  8927.                  aStream nextPut: $.; cr].
  8928.              aStream tab; nextPutAll: 'self propagateFrom: ins to: '.
  8929.              entry outVar thingDataCodeStringOn: aStream.
  8930.              aStream nextPut: $.; cr]].!
  8931.  
  8932. compile: aString in: moduleClass dontExpand: dontExpand
  8933.     "Compile the given method string in the given class. Variables in the collection dontExpand will not be expanded in line."
  8934.  
  8935.     | methodNode selector |
  8936.     methodNode _ EquationParser parse: aString readStream in: moduleClass.
  8937.     selector _ methodNode selector.
  8938.     self optimize: (methodNode block statements) dontExpand: dontExpand.
  8939.     methodNode block returnSelfIfNoOther.    "add '^self'"
  8940.     moduleClass addSelector: selector withMethod: (methodNode generate).
  8941.     moduleClass organization classify: selector under: 'module methods' asSymbol.!
  8942.  
  8943. compileExecuteIn: moduleClass prefix: prefix codeString: codeString varTable: varTable
  8944.     "Compile the 'xxxExecute' method in the given class."
  8945.  
  8946.     | s internals |
  8947.     s _ (String new: 1000) writeStream.
  8948.     s nextPutAll: prefix, 'execute'.
  8949.     s cr; cr.
  8950.     self putPrefixOn: s varTable: varTable.
  8951.     s nextPutAll: codeString.
  8952.     self putPostfixOn: s.
  8953.     internals _ (varTable select: [: v | v isInternal]) collect: [: v | v name].
  8954.     self
  8955.         compile: (s contents)
  8956.         in: moduleClass
  8957.         dontExpand: internals asSet.!
  8958.  
  8959. compileIsPossibleIn: moduleClass prefix: prefix
  8960.     "Compile the 'xxxIsPossible' method in the given class."
  8961.  
  8962.     | s |
  8963.     s _ (String new: 1000) writeStream.
  8964.     s nextPutAll: prefix, 'isPossible'.
  8965.     s cr; cr; tab; nextPut: $^; cr.
  8966.     isPossibleEquation storeOn: s.
  8967.     self compile: (s contents)
  8968.         in: moduleClass
  8969.         dontExpand: #().!
  8970.  
  8971. compilePropagateIn: moduleClass prefix: prefix
  8972.     "Compile the 'xxxPropagate' method in the given class."
  8973.  
  8974.     | s temp |
  8975.     s _ (String new: 1000) writeStream.
  8976.     s nextPutAll: prefix, 'propagate'.
  8977.     s cr; cr.
  8978.     self ancestorsAndStayCodeOn: s.
  8979.     s cr.
  8980.  
  8981.     "generate code for the walkabout strength computations for all outputs not completely determined by stay constraints"
  8982.     dependencies with: outWalkEqns do:
  8983.         [: entry : eqn |
  8984.          (entry stay not) ifTrue:
  8985.             [s tab.
  8986.              (entry outVar) thingDataCodeStringOn: s.
  8987.              s nextPutAll: ' walkStrength: '; cr; tab; tab.
  8988.              eqn storeOn: s.
  8989.              s nextPut: $.; cr]].
  8990.  
  8991.     "compile the 'isPossible' method"
  8992.     self compile: (s contents)
  8993.         in: moduleClass
  8994.         dontExpand: #().!
  8995.  
  8996. putPostfixOn: aStream
  8997.     "Answer a string to be used as the postfix when compiling my method. Statements are created to store the values of all outputs temporaries in their final destinations."
  8998.  
  8999.     | outVar |
  9000.     dependencies do:
  9001.         [: d |
  9002.          ((d stay) & (d dependsOn isEmpty)) ifFalse:    "not just a stay constraint"
  9003.             [outVar _ d outVar.
  9004.              aStream tab.
  9005.              outVar putCodeStringOn: aStream.
  9006.              aStream nextPutAll: outVar name.
  9007.              aStream nextPut: $.; cr]].!
  9008.  
  9009. putPrefixOn: aStream varTable: varTable
  9010.     "Append to the given stream a prefix to be used when compiling my execute method. Assignments statements are created to fetch the value of all variables into temporary variables. Unnecessary assignments statements are later removed during code optimization."
  9011.  
  9012.     varTable do:
  9013.         [: var |
  9014.         (var isExternal) ifTrue:
  9015.             [aStream tab; nextPutAll: var name, ' _ '.
  9016.              var getCodeStringOn: aStream.
  9017.              aStream nextPut: $.; cr]].! !
  9018.  
  9019. !ModuleSolution methodsFor: 'private-optimization'!
  9020.  
  9021. detectInlineCandidateIn: statements dontExpand: dontExpand
  9022.     "Find a candidate assignement statement for inline expansion from the given list of statements. Answer the index of the candidate statement or nil if we don't find one."
  9023.  
  9024.     | node v |
  9025.     1 to: statements size do:
  9026.         [: index |
  9027.          node _ statements at: index.
  9028.          (node isMemberOf: AssignmentNode) ifTrue:
  9029.             [v _ node variable name.
  9030.                (((dontExpand includes: v) not) and:
  9031.               [(self var: v isNotAssignedToAfter: index in: statements) and:
  9032.                [(self var: v usageCountAfter: index in: statements) <= 1]])
  9033.                     ifTrue: [^index]]].
  9034.     ^nil!
  9035.  
  9036. detectUnneededCandidateIn: statements
  9037.     "Select a candidate unnecessary assignement statement from the given list of statements. Answer the index of the candidate statement or nil if we don't find one."
  9038.  
  9039.     | node var |
  9040.     1 to: statements size do:
  9041.         [: index |
  9042.          node _ statements at: index.
  9043.          ((node isMemberOf: AssignmentNode) and:
  9044.           [node variable isTemp]) ifTrue:
  9045.             [var _ node variable name.
  9046.                ((self var: var usageCountAfter: index in: statements) = 0)
  9047.                 ifTrue: [^index]]].
  9048.     ^nil!
  9049.  
  9050. optimize: statements dontExpand: dontExpand
  9051.     "Do inline expansions on the given OrderedCollection of statements. The statement list is modified in place."
  9052.     "Algorithm:
  9053.      Repeat until nothing more can be done:
  9054.         find an assignment statement s of the form 'v _ expr' such that
  9055.             v is not in dontExpand AND
  9056.             v is used at most once in the remaining statements AND
  9057.             v is not assigned to in the remaining statements
  9058.         remove s from the statements list
  9059.         replace references to v with expr
  9060. Also, remove assignments to temporary variables that are never referenced in subsequent statements."
  9061.  
  9062.     | index s |
  9063.     [true] whileTrue:
  9064.         [index _    self detectInlineCandidateIn: statements dontExpand: dontExpand.
  9065.          (index isNil) ifTrue: [^self].     "nothing more to do"
  9066.          s _ statements removeAtIndex: index.
  9067.          self replace: (s variable name) with: (s value) in: statements after: index].
  9068.  
  9069.     "remove unneeded assignments to temporary variables"
  9070.     [true] whileTrue:
  9071.         [index _    self detectUnneededCandidateIn: statements.
  9072.          (index isNil) ifTrue: [^self].     "nothing more to do"
  9073.          s _ statements removeAtIndex: index].!
  9074.  
  9075. replace: var with: expr in: statements after: index
  9076.     "Replace the given variable with the given expression in the statements following index in the given list."
  9077.  
  9078.     | old new |
  9079.     index to: statements size do:
  9080.         [: i |
  9081.          old _ statements at: i.
  9082.          new _ old transformBy:
  9083.             [: node |
  9084.              ((node isMemberOf: VariableNode) and:
  9085.                [node name = var])
  9086.                 ifTrue: [expr transformBy: [: n | n] "copies expr tree"]
  9087.                 ifFalse: [node]].
  9088.          statements at: i put: new].!
  9089.  
  9090. var: var isNotAssignedToAfter: index in: statements
  9091.     "Answer true if the given variable is not assigned to after the statement with the given index in the given list of statements."
  9092.  
  9093.     | s |
  9094.     (index + 1) to: statements size do:
  9095.         [: i |
  9096.          (statements at: i) apply:
  9097.             [: node |
  9098.              ((node isMemberOf: AssignmentNode) and:
  9099.                [node variable name = var]) ifTrue:
  9100.                 [^false].
  9101.              true    "apply this block to the entire tree"]].
  9102.  
  9103.     ^true!
  9104.  
  9105. var: var usageCountAfter: index in: statements
  9106.     "Answer the number of times that the given variable is referenced after the statement with the given index in the given list of statements."
  9107.  
  9108.     | count |
  9109.     count _ 0.
  9110.     (index + 1) to: statements size do:
  9111.         [: i |
  9112.          (statements at: i) apply:
  9113.             [: node |
  9114.              ((node isMemberOf: VariableNode) and:
  9115.                [node name = var]) ifTrue:
  9116.                 [count _ count + 1].
  9117.              true    "apply this block to the entire tree"]].
  9118.     ^count! !
  9119.  
  9120. !ModuleSolution methodsFor: 'printing'!
  9121.  
  9122. printOn: aStream
  9123.  
  9124.     aStream cr; nextPutAll: 'ModuleSolution['.
  9125.     methods do:
  9126.         [: m |
  9127.          (m isNil) ifTrue: [aStream cr].
  9128.          m printOn: aStream].
  9129.     aStream nextPutAll: ']'.! !
  9130. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9131.  
  9132. ModuleSolution class
  9133.     instanceVariableNames: ''!
  9134.  
  9135.  
  9136. !ModuleSolution class methodsFor: 'instance creation'!
  9137.  
  9138. on: methodList
  9139.     "Answer a new instance for the given solution."
  9140.  
  9141.     ^self new methods: methodList! !
  9142.  
  9143. AbstractMethod subclass: #OffsetMethod
  9144.     instanceVariableNames: 'offset '
  9145.     classVariableNames: ''
  9146.     poolDictionaries: ''
  9147.     category: 'ThingLabII-Constraints-Special'!
  9148.  
  9149.  
  9150. !OffsetMethod methodsFor: 'initialize-release'!
  9151.  
  9152. offset: aNumber
  9153.  
  9154.     offset _ aNumber.! !
  9155.  
  9156. !OffsetMethod methodsFor: 'DeltaBlue'!
  9157.  
  9158. execute: refList
  9159.     "Execute myself to enforce my constraint. refList contains all the References for my constraint."
  9160.     "Details: If my first reference is the output, then compute it by adding the offset to the value of the first reference. If my first reference is the input, do the inverse operation (subtracting the offset)."
  9161.  
  9162.     (bindings first == $i)
  9163.         ifTrue: [(refList at: 2) value: ((refList at: 1) value + offset)]
  9164.         ifFalse: [(refList at: 1) value: ((refList at: 2) value - offset)].! !
  9165.  
  9166. ActionMenu subclass: #CustomMenu
  9167.     instanceVariableNames: 'items lastLine '
  9168.     classVariableNames: ''
  9169.     poolDictionaries: ''
  9170.     category: 'ThingLabII-UI-Framework'!
  9171. CustomMenu comment:
  9172. 'I am used to build menus on-the-fly. I maintain lists of menu items, actions (usually symbols to be sent as messages), and menu section dividing lines to which my clients may append new entries and lines by sending me the messages:
  9173.  
  9174.     add: aString action: anAction
  9175.     addLine
  9176.  
  9177. After the menu is constructed, it may be invoked with one of the following messages:
  9178.  
  9179.     invoke: initialSelection
  9180.     invoke
  9181.  
  9182. I am a subclass of ActionMenu, so I inherit a number of instance variables. The ones I am particularly concerned with are:
  9183.  
  9184.     items _ an OrderedCollection of strings to appear in the menu
  9185.     selectors _ an OrderedCollection of Symbols to be used as message selectors
  9186.     lineArray _ an OrderedCollection of line positions
  9187.     lastLine _ used to keep track of the last line to avoid making duplicate entries in lineArray'!
  9188.  
  9189.  
  9190. !CustomMenu methodsFor: 'initialize-release'!
  9191.  
  9192. initialize
  9193.  
  9194.     items _ OrderedCollection new.
  9195.     selectors _ OrderedCollection new.
  9196.     lineArray _ OrderedCollection new.
  9197.     lastLine _ 0.! !
  9198.  
  9199. !CustomMenu methodsFor: 'construction'!
  9200.  
  9201. add: aString action: aSymbol
  9202.     "Add the given string as the next menu item. If it is selected, the given action (usually but not necessarily a symbol) will be returned to the client."
  9203.  
  9204.     items addLast: aString.
  9205.     selectors addLast: aSymbol.!
  9206.  
  9207. addLine
  9208.     "Append a line to the menu after the last entry. Suppress duplicate lines."
  9209.  
  9210.     (lastLine ~= items size)
  9211.         ifTrue:
  9212.             [lastLine _ items size.
  9213.              lineArray addLast: lastLine].! !
  9214.  
  9215. !CustomMenu methodsFor: 'invocation'!
  9216.  
  9217. invoke
  9218.     "Invoke the menu with no initial selection."
  9219.  
  9220.     ^self invoke: nil!
  9221.  
  9222. invoke: initialSelection
  9223.     "Invoke the menu with the given initial selection (i.e. one of my 'action' symbols). Answer the 'action' selector associated with the menu item chosen by the user or nil if none is chosen."
  9224.  
  9225.     | itemIndex |
  9226.     self build.
  9227.     (initialSelection notNil)
  9228.         ifTrue: [self preSelect: initialSelection].
  9229.     itemIndex _ self startUp.
  9230.     (itemIndex = 0)
  9231.         ifTrue: [^nil]
  9232.         ifFalse: [^selectors at: itemIndex].! !
  9233.  
  9234. !CustomMenu methodsFor: 'private'!
  9235.  
  9236. build
  9237.     "Turn myself into an invokable ActionMenu."
  9238.  
  9239.     | stream itemIndex |
  9240.     stream _ WriteStream on: (String new).
  9241.     items do: [: item | stream nextPutAll: item; cr].
  9242.     (items isEmpty)
  9243.         ifFalse: [stream skip: -1].     "remove last cr"
  9244.     self labels: stream contents font: (TextStyle default fontAt: 1) lines: lineArray.!
  9245.  
  9246. preSelect: action
  9247.     "Pre-select and highlight the menu item associated with the given action."
  9248.  
  9249.     | i |
  9250.     i _ selectors indexOf: action ifAbsent: [^self].
  9251.     self reset.
  9252.     marker _ marker 
  9253.         align: marker topLeft 
  9254.         with: (marker left)@(frame inside top + (marker height * (i - 1))).
  9255.     selection _ i.! !
  9256. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9257.  
  9258. CustomMenu class
  9259.     instanceVariableNames: ''!
  9260.  
  9261.  
  9262. !CustomMenu class methodsFor: 'instance creation'!
  9263.  
  9264. new
  9265.  
  9266.     ^(super new) initialize! !
  9267.  
  9268. !CustomMenu class methodsFor: 'example'!
  9269.  
  9270. example
  9271.     "CustomMenu example"
  9272.  
  9273.     | menu |
  9274.     menu _ CustomMenu new.
  9275.     menu add: 'apples' action: #apples.
  9276.     menu add: 'oranges' action: #oranges.
  9277.     menu add: 'peaches' action: #peaches.
  9278.     menu add: 'pears' action: #pears.
  9279.     ^menu invoke: #peaches! !
  9280.  
  9281. Thing subclass: #ModuleThing
  9282.     instanceVariableNames: ''
  9283.     classVariableNames: ''
  9284.     poolDictionaries: ''
  9285.     category: 'ThingLabII-Things'!
  9286. ModuleThing comment:
  9287. 'I am an abstract class for compiled ThingLabII Things. These Things are known as Modules. Do NOT EVER subclass a subclass of ModuleThing. Very bad!!  Even worse than for Things.
  9288.  
  9289. My protocol is fairly simple because most of the work is done at compile time.
  9290. '!
  9291.  
  9292.  
  9293. !ModuleThing methodsFor: 'public-testing'!
  9294.  
  9295. isStructureModifiable
  9296.     "Modules cannot be further modified."
  9297.  
  9298.     ^false! !
  9299.  
  9300. !ModuleThing methodsFor: 'cloning'!
  9301.  
  9302. clonePass1: cloneDictionary
  9303.     "ModuleThings must clone their internal parts as well as their normal parts."
  9304.  
  9305.     | myClone oldPart newPart |
  9306.     myClone _ super clonePass1: cloneDictionary.
  9307.     "clone my internal parts"
  9308.     (super class instOffset + 1) to: (self class instOffset) do:
  9309.         [: i |
  9310.          oldPart _ self instVarAt: i.
  9311.          newPart _ oldPart cloneUsing: cloneDictionary.
  9312.          myClone instVarAt: i put: newPart].
  9313.     "redundant, but good documentation:"
  9314.     cloneDictionary at: self put: myClone.
  9315.     ^myClone! !
  9316.  
  9317. !ModuleThing methodsFor: 'DeltaBlue'!
  9318.  
  9319. propagateFrom: inDatas to: outData
  9320.     "Used by ModuleMethods to propagate stay values from the given inputs to the given output."
  9321.  
  9322.     outData stay:
  9323.         ((inDatas isEmpty) or:
  9324.           [(inDatas detect: [: var | var stay not] ifNone: [nil]) isNil]).! !
  9325. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9326.  
  9327. ModuleThing class
  9328.     instanceVariableNames: 'constructionView '!
  9329.  
  9330.  
  9331. !ModuleThing class methodsFor: 'initialize and destroy'!
  9332.  
  9333. destroy
  9334.     "Eliminate useView/constructionView circularities before destroying this class."
  9335.  
  9336.     (constructionView notNil) ifTrue:
  9337.         [constructionView useView: nil].
  9338.     constructionView _ nil.
  9339.     super destroy.!
  9340.  
  9341. initializeForSourceClass: sourceThingClass internalPartCount: internalPartCount
  9342.     "Initialize a new ModuleThing class created from the given source class."
  9343.  
  9344.     | instVarNames |
  9345.     partIcon _ sourceThingClass partIcon deepCopy.
  9346.     explainText _ 'This is a compiled Module. It was compiled from ', sourceThingClass name, '.'.
  9347.     externalParts _ OrderedCollection new.
  9348.     instVarNames _ self instVarNames.
  9349.     partNamesAndIndices _ OrderedCollection new: instVarNames size.
  9350.     1 to: instVarNames size do:
  9351.         [: i |
  9352.          (i > internalPartCount) ifTrue:
  9353.              [partNamesAndIndices addLast:
  9354.                 (Array
  9355.                     with: (instVarNames at: i) asSymbol
  9356.                     with: (self instOffset + i))]].
  9357.     useView _ nil.
  9358.     constructionView _ sourceThingClass.
  9359.     prototype _ self basicNew initialize.! !
  9360.  
  9361. !ModuleThing class methodsFor: 'access'!
  9362.  
  9363. constructionView
  9364.     "Answer the class of the Thing that was compiled to create me."
  9365.  
  9366.     ^constructionView!
  9367.  
  9368. constructionView: aThingClass
  9369.     "Set the class of the Thing that was compiled to create me."
  9370.  
  9371.     constructionView _ aThingClass.! !
  9372.  
  9373. !ModuleThing class methodsFor: 'private-compiling'!
  9374.  
  9375. compileInstOffsetMethodAs: size
  9376.     "Compile the instOffset method for this class of the form:
  9377.  
  9378.         instOffset
  9379.             ^NNN
  9380.     where NNN is the number of internal variable plus the instOffset for normal Things."
  9381.  
  9382.     | sel encoder returnNode block methodNode |
  9383.     sel _ #instOffset.
  9384.     encoder _ (Encoder new) init: self class context: nil notifying: self.
  9385.     returnNode _ ReturnNode new expr: (encoder encodeLiteral: size).
  9386.     block _ BlockNode new
  9387.         statements: (OrderedCollection with: returnNode)
  9388.         returns: true.
  9389.     methodNode _ MethodNode new
  9390.         selector: sel
  9391.         arguments: #()
  9392.         precedence: sel precedence
  9393.         temporaries: #()
  9394.         block: block
  9395.         encoder: encoder
  9396.         primitive: 0.
  9397.     self class addSelector: sel withMethod: (methodNode generate).
  9398.     self class organization classify: sel under: 'inst var access' asSymbol.! !
  9399.  
  9400. StandardSystemController subclass: #SpecialSystemController
  9401.     instanceVariableNames: 'fromFrame fromHolder '
  9402.     classVariableNames: 'BlueButtonMenu '
  9403.     poolDictionaries: ''
  9404.     category: 'ThingLabII-UI-Support'!
  9405.  
  9406.  
  9407. !SpecialSystemController methodsFor: 'accessing'!
  9408.  
  9409. fromFrame
  9410.  
  9411.     ^fromFrame!
  9412.  
  9413. fromFrame: aRectangle
  9414.  
  9415.     fromFrame _ aRectangle!
  9416.  
  9417. fromHolder
  9418.  
  9419.     ^fromHolder!
  9420.  
  9421. fromHolder: aPartHolder
  9422.  
  9423.     fromHolder _ aPartHolder! !
  9424.  
  9425. !SpecialSystemController methodsFor: 'queries'!
  9426.  
  9427. isVisible
  9428.  
  9429.     ^status ~= #closed! !
  9430.  
  9431. !SpecialSystemController methodsFor: 'menu messages'!
  9432.  
  9433. blueButtonActivity
  9434.     "Use special menu if collapsed. Otherwise, use my custom blueButtonMenu, which omits 'collapse'."
  9435.  
  9436.     | selector i |
  9437.     view isCollapsed
  9438.         ifTrue: [^super blueButtonActivity].
  9439.  
  9440.     (BlueButtonMenu isNil) ifTrue:
  9441.         [BlueButtonMenu _ ActionMenu
  9442.             labels: ' under \ move \ frame \ close ' withCRs
  9443.             lines: #(3)
  9444.             selectors: #(under move frame close)].
  9445.     i _ BlueButtonMenu startUp.
  9446.     (i > 0) ifTrue: [self perform: (BlueButtonMenu selectorAt: i)].!
  9447.  
  9448. close
  9449.     "Do zooming animation and remember the current view display box on close. In order to do the animation, fromFrame must be non-nil and in order to remember the display box fromHolder must be non-nil."
  9450.  
  9451.     model changeRequest ifFalse: [^self].
  9452.     status _ #closed.
  9453.     view erase.
  9454.     (fromHolder notNil)
  9455.         ifTrue: [fromHolder lastFrame: (view displayBox)].
  9456.     (fromFrame notNil)
  9457.         ifTrue: [Display zoom: view displayBox to: fromFrame duration: 260].
  9458.     super close.!
  9459.  
  9460. controlActivity
  9461.  
  9462.     (sensor blueButtonPressed and: [self viewHasCursor])
  9463.         ifTrue: [^self blueButtonActivity].
  9464.     (sensor redButtonPressed and:
  9465.       [view labelDisplayBox containsPoint: sensor cursorPoint])
  9466.         ifTrue: [^self redButtonActivity].
  9467.     self controlToNextLevel.!
  9468.  
  9469. redButtonActivity
  9470.     "Give access to menus when the mouse (red button) goes down in the label part of my view. If the mouse is in the text box, act as though the yellow button were pressed (the application menu, by convention) otherwise, act as though the blue button were pressed (the view menu, by convention)."
  9471.  
  9472.     | p |
  9473.     p _ sensor cursorPoint.
  9474.     (view labelDisplayBox containsPoint: p)
  9475.         ifTrue:
  9476.             [((view labelTextDisplayBox containsPoint: p) and:
  9477.                [view firstSubView notNil])
  9478.                 ifTrue:
  9479.                     [(view firstSubView controller respondsTo: #menuActivity) ifTrue:
  9480.                         [view firstSubView controller menuActivity].
  9481.                       (view firstSubView controller respondsTo: #yellowButtonActivity) ifTrue:
  9482.                         [view firstSubView controller yellowButtonActivity]]
  9483.                 ifFalse: [self blueButtonActivity]]
  9484.         ifFalse: [].! !
  9485.  
  9486. BasicThingView subclass: #MultiThingView
  9487.     instanceVariableNames: ''
  9488.     classVariableNames: ''
  9489.     poolDictionaries: ''
  9490.     category: 'ThingLabII-UI-Thing Views'!
  9491.  
  9492.  
  9493. !MultiThingView methodsFor: 'controller access'!
  9494.  
  9495. defaultControllerClass
  9496.  
  9497.     ^MultiThingController! !
  9498.  
  9499. !MultiThingView methodsFor: 'operations'!
  9500.  
  9501. acceptCopies: thingHolders at: offsets withRespectTo: ignored
  9502.     "Insert copies of the given Things."
  9503.  
  9504.     thingHolders do:
  9505.         [: thingHolder | model addGlyph: (thingHolder cargo clone)].
  9506.     self displayView.! !
  9507. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9508.  
  9509. MultiThingView class
  9510.     instanceVariableNames: ''!
  9511.  
  9512.  
  9513. !MultiThingView class methodsFor: 'instance creation'!
  9514.  
  9515. on: aMultiThingAdaptor
  9516.     "Answer a new view on the given object."
  9517.  
  9518.     ^(self new) model: aMultiThingAdaptor!
  9519.  
  9520. open
  9521.     "Open an empty view."
  9522.  
  9523.     self
  9524.         openWithSubview: (self new model: MultiThingAdaptor new)
  9525.         label: 'MultiThing View'.! !
  9526.  
  9527. Constraint subclass: #OffsetConstraint
  9528.     instanceVariableNames: ''
  9529.     classVariableNames: 'SharedMethods '
  9530.     poolDictionaries: ''
  9531.     category: 'ThingLabII-Constraints-Special'!
  9532. OffsetConstraint comment:
  9533. 'I am used to relate two variables by a fixed offset.'!
  9534.  
  9535.  
  9536. !OffsetConstraint methodsFor: 'initialize-release'!
  9537.  
  9538. ref: ref1 ref: ref2 strength: aSymbol offset: offset
  9539.     "Initialize myself with the given references, strength, and offset."
  9540.  
  9541.     strength _ Strength of: aSymbol.
  9542.     symbols _ #(v1 v2).
  9543.     self variables: (Array with: ref1 with: ref2).
  9544.     self methods: (self getMethodsFor: offset).
  9545.     whichMethod _ nil.
  9546.     self initializeFlags.! !
  9547.  
  9548. !OffsetConstraint methodsFor: 'private'!
  9549.  
  9550. getMethodsFor: offset
  9551.     "To save space, we maintain a Dictionary of shared methods for offsets in the range [-25..25]. Answer the methods array from this Dictionary or a newly created one."
  9552.  
  9553.     | offsetMethods |
  9554.     (SharedMethods isNil) ifTrue:
  9555.         [SharedMethods _ Dictionary new: 100].
  9556.     ((offset isInteger) & (offset >= -25) & (offset <= 25))
  9557.         ifTrue:            "cached methods"
  9558.             [offsetMethods _ SharedMethods
  9559.                 at: offset
  9560.                 ifAbsent: [self makeMethodsFor: offset].
  9561.              SharedMethods at: offset put: offsetMethods]
  9562.         ifFalse:            "non-integer or unusual size offset"
  9563.             [offsetMethods _ self makeMethodsFor: offset].
  9564.     ^offsetMethods!
  9565.  
  9566. makeMethodsFor: offset
  9567.     "Construct and answer a pair of OffsetMethods for the given offset."
  9568.  
  9569.     ^Array
  9570.         with: ((OffsetMethod new)
  9571.             codeString: 'v2 _ v1 + ', offset printString;
  9572.             offset: offset;
  9573.             bindings: 'io')
  9574.         with: ((OffsetMethod new)
  9575.             codeString: 'v1 _ v2 - ', offset printString;
  9576.             offset: offset;
  9577.             bindings: 'oi')! !
  9578. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9579.  
  9580. OffsetConstraint class
  9581.     instanceVariableNames: ''!
  9582.  
  9583.  
  9584. !OffsetConstraint class methodsFor: 'instance creation'!
  9585.  
  9586. from: ref1 to: ref2 require: aNumber
  9587.     "Create an OffsetConstraint on the referenced variable. For example:
  9588.  
  9589.     OffsetConstraint
  9590.         from: point1->#x
  9591.         to: point2->#x
  9592.         require: 25."
  9593.  
  9594.     ^(super new) ref: ref1 ref: ref2 strength: #required offset: aNumber!
  9595.  
  9596. ref: ref1 ref: ref2 strength: strength offset: aNumber
  9597.     "Create an OffsetConstraint on the referenced variable. For example:
  9598.  
  9599.     OffsetConstraint
  9600.         ref: point1->#x
  9601.         ref: point2->#x
  9602.         strength: #preferred
  9603.         offset: 25."
  9604.  
  9605.     ^(super new) ref: ref1 ref: ref2 strength: strength offset: aNumber! !
  9606.  
  9607. BasicThingView subclass: #ThingConstructorView
  9608.     instanceVariableNames: ''
  9609.     classVariableNames: ''
  9610.     poolDictionaries: ''
  9611.     category: 'ThingLabII-UI-Thing Views'!
  9612.  
  9613.  
  9614. !ThingConstructorView methodsFor: 'controller access'!
  9615.  
  9616. defaultControllerClass
  9617.  
  9618.     ^ThingConstructorController! !
  9619.  
  9620. !ThingConstructorView methodsFor: 'operations'!
  9621.  
  9622. acceptCopies: thingHolders at: offsets withRespectTo: ignored
  9623.     "Insert copies of the given Things and allow the user to connect up their inserters."
  9624.  
  9625.     | newPart |
  9626.      (model thing isStructureModifiable)
  9627.         ifFalse: [^self flash].
  9628.  
  9629.     thingHolders do:
  9630.         [: thingHolder |
  9631.          self displaySafe: [controller insertThing: (thingHolder cargo)]].! !
  9632.  
  9633. Object subclass: #MultiSolver
  9634.     instanceVariableNames: 'constraints externalVars modeTable modeStrength methods satisfied determined solutions variables transitions '
  9635.     classVariableNames: ''
  9636.     poolDictionaries: ''
  9637.     category: 'ThingLabII-Module Compiler'!
  9638. MultiSolver comment:
  9639. 'I am used by the ModuleCompiler and the Thing debugger to enumerate the possible solutions to a set of constraints. There are various options to control which possibilities are presented. One may get all possible solutions, only those without cycles, or only those that without cycles that have unique input/output modes.'!
  9640.  
  9641.  
  9642. !MultiSolver methodsFor: 'initialization'!
  9643.  
  9644. constraints: constraintList
  9645.     "Initialize myself with the constraints of the given collection."
  9646.  
  9647.     | sorter |
  9648.     "sort constraints in order of decreasing strength"
  9649.     sorter _ (SortedCollection new: 100)
  9650.                 sortBlock: [: i : j | i strength stronger: j strength].
  9651.     sorter addAll: constraintList.
  9652.     constraints _ sorter asOrderedCollection.
  9653.  
  9654.     "re-order the constraints in constraintList to match constraints"
  9655.     constraintList setIndices.    "empties constraintList"
  9656.     constraintList addAll: constraints.
  9657.     sorter release.
  9658.     self buildVariableDictionary.
  9659.     externalVars _ IdentitySet new.
  9660.     modeTable _ modeStrength _ nil.!
  9661.  
  9662. constraints: constraintList externalVars: extVarList
  9663.     "Initialize myself with the given constraints and external variables."
  9664.  
  9665.     self constraints: constraintList.
  9666.     externalVars _ IdentitySet new: extVarList size.
  9667.     externalVars addAll: extVarList.
  9668.     modeTable _ Dictionary new.
  9669.     modeStrength _ Dictionary new.! !
  9670.  
  9671. !MultiSolver methodsFor: 'public'!
  9672.  
  9673. allSolutions
  9674.     "Answer all the solutions, even those that contain cycles."
  9675.  
  9676.     ^solutions!
  9677.  
  9678. computeSolutions
  9679.     "Compute and remember all legal solutions to my set of constraints."
  9680.  
  9681.     methods _ OrderedCollection new: constraints size.
  9682.     satisfied _ IdentitySet new: (constraints size * 4).
  9683.     determined _ IdentitySet new: 30.
  9684.     solutions _ OrderedCollection new: 100.
  9685.     self possibleNextMethods do:
  9686.         [: m | self solutionsUsing: m].!
  9687.  
  9688. nonCyclicSolutions
  9689.     "Answer all non-cyclic solutions. This can take some time if there are a large number of solutions."
  9690.  
  9691.     ^solutions select: [: s | (self hasCycle: s) not]!
  9692.  
  9693. uniqueModeSolutions
  9694.     "Answer a set of non-cyclic solutions that handle mutually exclusive input/output modes over the external variables. This can only be done if I know what the external variables are (i.e. if my modeTable is not nil)."
  9695.  
  9696.     | solutionSet |
  9697.     (modeTable isNil) ifTrue:
  9698.         [^self error: 'The external variables were not defined.'
  9699.          "use the constraints:externalVars: initialization message"].
  9700.  
  9701.     solutionSet _ OrderedCollection new: modeTable size.
  9702.     modeTable do: [: solution | solutionSet add: solution].
  9703.     ^solutionSet! !
  9704.  
  9705. !MultiSolver methodsFor: 'private-find solutions'!
  9706.  
  9707. couldUse: aMethod for: theConstraint
  9708.     "Answer true if the given constraint is stronger than all unsatisfied constraints that could potentially determine the given method's outputs. If any of the method's outputs are external variables, we can't be sure that it is strong enough. We assume that the given method is possible -- that is, that none of its outputs is already determined by another constraint."
  9709.  
  9710.     | maxOutStrength |
  9711.     maxOutStrength _ Strength absoluteWeakest.
  9712.     aMethod outDatasIn: theConstraint thingDatas do:
  9713.         [: outVar |    "examine all output vars of the method"
  9714.          (externalVars includes: outVar) ifTrue: [^false].
  9715.          outVar constraints do:
  9716.             [: c |    "examine all unsatisfied constraints except theConstraint"
  9717.              ((c ~~ theConstraint) and:
  9718.               [(satisfied includes: c) not]) ifTrue:
  9719.                 [maxOutStrength _
  9720.                     maxOutStrength strongest: c strength]]].
  9721.  
  9722.     ^theConstraint strength stronger: maxOutStrength!
  9723.  
  9724. modeVector
  9725.     "Answer a mode vector for the current solution. A mode vector is a string of 'i' and 'o' characters (e.g. 'iio') that indicates whether each var in externalVars is an input or output."
  9726.     "Details: v is output if it is in determined OR if it is an output of the last method (if that method isn't nil). We have to check the last method outputs because the last method's outputs are not recorded in determined to save cost of copying determined (for backtracking). This is a messy efficiency hack that saves about 12%; it would be cleaner to to update and restore 'determined' even when processing the last method."
  9727.  
  9728.     | lastMethodOuts modeVector i |
  9729.     lastMethodOuts _ IdentitySet new.
  9730.     (methods last notNil) ifTrue:
  9731.         [methods last outDatasIn: (constraints last thingDatas) do:
  9732.             [: out | lastMethodOuts add: out]].
  9733.  
  9734.     modeVector _ String new: externalVars size.
  9735.     i _ 1.
  9736.     externalVars do:
  9737.         [: v |
  9738.          ((determined includes: v) or:
  9739.           [lastMethodOuts includes: v])
  9740.             ifTrue: [modeVector at: i put: $o]
  9741.             ifFalse: [modeVector at: i put: $i].
  9742.          i _ i + 1].
  9743.     ^modeVector!
  9744.  
  9745. nilAllowedFor: theConstraint possibleMethods: possibleMethods
  9746.     "Consider the given set of possible methods for the given constraint and answer true if the nil method is allowed. If the constraint is required or if it can be satisfied without interferring with any stronger constraint, the nil method is not allowed."
  9747.  
  9748.     "If the constraint is required, nil is not allowed."
  9749.     (theConstraint isRequired) ifTrue: [^false].
  9750.  
  9751.     "
  9752. Look for a method that could be used to satisfy the given constraint without interferring with a stronger constraint. If we find one, don't allow nil as a possible method."
  9753.     possibleMethods do:
  9754.         [: m |
  9755.          (self couldUse: m for: theConstraint) ifTrue: [^false]].
  9756.  
  9757.     ^true    "nil method is okay"!
  9758.  
  9759. outputsOf: aMethod notDeterminedFor: aConstraint
  9760.     "Answer true if none of the outputs of the given method has been determined."
  9761.  
  9762.     aMethod outDatasIn: aConstraint thingDatas do:
  9763.         [: outVar |
  9764.          (determined includes: outVar) ifTrue: [^false]].
  9765.     ^true    "none of the outputs has been determined"!
  9766.  
  9767. possibleNextMethods
  9768.     "Answer a collection of possible methods for solving the next constraint. A nil in this collection means that the constraint need not be satisfied."
  9769.  
  9770.     | c possibleMethods |
  9771.     c _ constraints at: (methods size + 1).
  9772.     possibleMethods _ c methods select:
  9773.         [: m | self outputsOf: m notDeterminedFor: c].
  9774.  
  9775.     ^(self nilAllowedFor: c possibleMethods: possibleMethods)
  9776.         ifTrue: [possibleMethods copyWith: nil]
  9777.         ifFalse: [possibleMethods]!
  9778.  
  9779. recordSolution: aSolution
  9780.     "Record the given solution in the mode table, if there is one."
  9781.  
  9782.     | modeVec oldCost costOfThisSolution |
  9783.     solutions add: aSolution.
  9784.     (modeTable notNil) ifTrue:
  9785.         [modeVec _ self modeVector.
  9786.          oldCost _ modeStrength
  9787.             at: modeVec
  9788.             ifAbsent: [Strength absoluteStrongest].
  9789.          costOfThisSolution _
  9790.             self strengthOfStrongestUnsatisfiedConstraint: aSolution.
  9791.          ((costOfThisSolution weaker: oldCost) and:
  9792.            [(self hasCycle: aSolution) not]) ifTrue:
  9793.             [modeTable at: modeVec put: aSolution.
  9794.              modeStrength at: modeVec put: costOfThisSolution]].!
  9795.  
  9796. solutionsUsing: aMethod
  9797.     "Solve the current constraint using the given method then find all legal solutions reachable from this state. We use a recursive, depth-first enumeration technique."
  9798.     "Details: The list of currently determined constraints must be saved and then restored when we are done to allow proper backtracking. However, this list need only be copied if we are going to change it (i.e. the current constraint is satisfied and it is not the last constraint), so the copy is done lazily."
  9799.  
  9800.     | currentConstraint savedDetermined |
  9801.     currentConstraint _ constraints at: (methods size + 1).
  9802.  
  9803.     "save state and solve the current constraint with the given method"
  9804.     savedDetermined _ determined.        "make a copy later if necessary"
  9805.     methods addLast: aMethod.
  9806.     satisfied add: currentConstraint.
  9807.  
  9808.     (methods size = constraints size)
  9809.         ifTrue:
  9810.             ["record a finished solution"
  9811.              self recordSolution: methods copy]
  9812.         ifFalse: 
  9813.             [(aMethod notNil) ifTrue:
  9814.                 ["make a copy of determined before changing it"
  9815.                  savedDetermined _ determined copy.
  9816.                  aMethod outDatasIn: currentConstraint thingDatas do:
  9817.                     [: outVar | determined add: outVar]].
  9818.              "enumerate solutions from here"
  9819.              self possibleNextMethods do:
  9820.                 [: m | self solutionsUsing: m]].
  9821.  
  9822.     "restore state"
  9823.     satisfied remove: currentConstraint.
  9824.     methods removeLast.
  9825.     determined _ savedDetermined.!
  9826.  
  9827. strengthOfStrongestUnsatisfiedConstraint: aSolution
  9828.     "Answer the strength of the strongest unsatisfied constraint in the given solution or a Strength absoluteWeakest if all the constraints are satisfied."
  9829.  
  9830.     constraints with: aSolution do:
  9831.         [: constraint : method |
  9832.          (method isNil) ifTrue: [^constraint strength]].
  9833.     ^Strength absoluteWeakest! !
  9834.  
  9835. !MultiSolver methodsFor: 'private-cycle detector'!
  9836.  
  9837. buildVariableDictionary
  9838.     "Construct the variables map, a dictionary that maps each variable to its own row index. Also initializes the transition matrix."
  9839.  
  9840.     | var |
  9841.     variables _ IdentityDictionary new: 16.
  9842.     constraints do:
  9843.         [: c |
  9844.          (c variables) do:
  9845.             [: ref |
  9846.              var _ ref thingData.
  9847.              (variables includesKey: var) ifFalse:
  9848.                 [variables at: var put: (variables size + 1)]]].
  9849.  
  9850.     transitions _ (1 to: variables size) collect:
  9851.         [: i |     Array new: variables size withAll: false].!
  9852.  
  9853. hasCycle: methodList
  9854.     "Answer true if the given collection of methods contains a cycle."
  9855.     "Details: This is implemented by finding the transitive closure of the directed graph formed by the methods of methodList. If any variable is its own ancestor in the transitive closure then there is a cycle in the solution. We use a boolean matrix representation to compute the transitive closure. The element [i,j] of this matrix is true if the value of variable i depends directly or indirectly on the value of variable j in the dataflow given by the method list."
  9856.  
  9857.     | status |
  9858.     self initializeTransitionMatrix: methodList.
  9859.     status _ #progress.
  9860.     [status == #progress] whileTrue:
  9861.         [status _ self propagateAncestors.
  9862.          (status == #cycleDetected) ifTrue:
  9863.             [^true]].        "cycle detected"
  9864.  
  9865.     ^false    "no cycle detected"!
  9866.  
  9867. initializeTransitionMatrix: methodList
  9868.     "Initialize the transition matrix for the given list of methods. The entry at [i,j] in this matrix is true if variable j is an ancestor of variable i."
  9869.  
  9870.     | matrixSize i row j m thingDatas |
  9871.     "first, clear transition matrix"
  9872.     matrixSize _ transitions size.
  9873.     i _ matrixSize.
  9874.     [i > 0] whileTrue:
  9875.         [row _ transitions at: i.
  9876.          j _ matrixSize.
  9877.          [j > 0] whileTrue:
  9878.             [row at: j put: false.
  9879.              j _ j - 1].
  9880.          i _ i - 1].
  9881.  
  9882.     "now, register initial ancestors based on the methods"
  9883.     i _ methodList size.
  9884.     [i > 0] whileTrue:
  9885.         [m _ methodList at: i.
  9886.          (m notNil) ifTrue:
  9887.             [thingDatas _ (constraints at: i) thingDatas.
  9888.              m outDatasIn: thingDatas do:
  9889.                 [: out |
  9890.                  row _ transitions at: (variables at: out).
  9891.                  m inDatasIn: thingDatas do:
  9892.                     [: in | row at: (variables at: in) put: true]]].
  9893.          i _ i - 1].!
  9894.  
  9895. propagateAncestors
  9896.     "Make one pass over the transition matrix propagating the ancestors relation. Answer one of:
  9897.         #done -- if no progress was made
  9898.         #progress -- if progress was made but no cycle was detected
  9899.         #cycleDetected -- if a cycle was detected."
  9900.  
  9901.     | matrixSize progress i descendent row |
  9902.     matrixSize _ transitions size.
  9903.     progress _ false.
  9904.     i _ 1.
  9905.     [i <= matrixSize] whileTrue:
  9906.         [descendent _ 1.
  9907.          [descendent <= matrixSize] whileTrue:
  9908.             [row _ transitions at: descendent.
  9909.              (row at: i) ifTrue:
  9910.                 [(self propagateFrom: i to: descendent) ifTrue:
  9911.                     [progress _ true.
  9912.                       (row at: descendent) ifTrue:
  9913.                         [^#cycleDetected]]].
  9914.              descendent _ descendent + 1].
  9915.          i _ i + 1].
  9916.  
  9917.     progress
  9918.         ifTrue: [^#progress]
  9919.         ifFalse: [^#done].!
  9920.  
  9921. propagateFrom: sourceVar to: descendentVar
  9922.     "OR the ancestors of sourceVar (its row) into descendentVar's row. Answer true if descendentVar's row changed."
  9923.  
  9924.     | source dest changed i sourceSize |
  9925.     source _ transitions at: sourceVar.
  9926.     dest _ transitions at: descendentVar.
  9927.     changed _ false.
  9928.     i _ 1.
  9929.     sourceSize _ source size.
  9930.     [i <= sourceSize] whileTrue:
  9931.         [((dest at: i) not and: [source at: i]) ifTrue:
  9932.             [dest at: i put: true.
  9933.              changed _ true].
  9934.          i _ i + 1].
  9935.     ^changed! !
  9936. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9937.  
  9938. MultiSolver class
  9939.     instanceVariableNames: ''!
  9940.  
  9941.  
  9942. !MultiSolver class methodsFor: 'instance creation'!
  9943.  
  9944. on: constraintList
  9945.     "Answer a new instance for the given set of constraints. Do not compute the solutions until asked to do so."
  9946.  
  9947.     ^(self new)
  9948.         constraints: constraintList! !
  9949.  
  9950. !MultiSolver class methodsFor: 'queries'!
  9951.  
  9952. allSolutionsFor: constraintList
  9953.     "Answer all solutions to the given set of constraints, including those that are cyclic."
  9954.  
  9955.     ^(self on: constraintList)
  9956.         computeSolutions;
  9957.         allSolutions!
  9958.  
  9959. solutionsFor: constraintList
  9960.     "Answer a collection of non-cyclic solutions to the given list of constraints."
  9961.  
  9962.     ^(self on: constraintList)
  9963.         computeSolutions;
  9964.         nonCyclicSolutions!
  9965.  
  9966. solutionsFor: constraintList externalVars: extVarList
  9967.     "Answer a collection of cycle-free solutions to the given set of constraints but only include one solutions for each input/output 'mode' of the set of externally visible variables. For example, if a, b, and c are the external variables then the modes are (in, in, in), (in, in, out), (in, out, in), and five more."
  9968.  
  9969.     ^((self new)
  9970.         constraints: constraintList externalVars: extVarList;
  9971.         computeSolutions)
  9972.             uniqueModeSolutions! !
  9973.  
  9974. SceneView subclass: #ThingDebugView
  9975.     instanceVariableNames: ''
  9976.     classVariableNames: ''
  9977.     poolDictionaries: ''
  9978.     category: 'ThingLabII-UI-Debugger'!
  9979.  
  9980.  
  9981. !ThingDebugView methodsFor: 'controller access'!
  9982.  
  9983. defaultControllerClass
  9984.  
  9985.     ^ThingDebugController! !
  9986.  
  9987. !ThingDebugView methodsFor: 'displaying'!
  9988.  
  9989. computeBackground
  9990.     "Compute the backgroundForm and the two lists, visibleForeground and selectedForeground. These are used by the 'displayFeedback' and 'displayFeedbackWithBox:width:' operations."
  9991.  
  9992.     super computeBackground.
  9993.     self
  9994.         displaySolutionInfoOn: backgroundForm
  9995.         at: (self viewOrigin)
  9996.         clippingBox: (backgroundForm computeBoundingBox).!
  9997.  
  9998. displaySolutionInfoOn: aDisplayMedium at: aPoint clippingBox: clipBox
  9999.     "Display information about the number of solutions and partitions and whether there is a cycle in the currently selected solution."
  10000.  
  10001.     | infoBox printer |
  10002.     infoBox _ ((10@10 extent: 170@48) translateBy: aPoint)
  10003.                 intersect: clipBox.
  10004.     aDisplayMedium border: infoBox width: 1.
  10005.     printer _
  10006.         QuickPrint newOn: aDisplayMedium
  10007.         box: (infoBox topLeft + (40@4) corner: infoBox bottomRight).
  10008.     printer drawString:
  10009.         'Partition ', model partitionIndex printString,
  10010.         ' of ', model partitionCount printString.
  10011.     printer downBy: 14.
  10012.     (model solutionIndex = 0)
  10013.         ifTrue:
  10014.             [printer drawString: 'Current solution']
  10015.         ifFalse:
  10016.             [printer drawString:
  10017.                 'Alternative ', model solutionIndex printString,
  10018.                 ' of ', model solutionCount printString].
  10019.     printer downBy: 14.
  10020.      (model solutionHasCycle) ifTrue:
  10021.         [printer drawString: 'Cycle Detected!!'].! !
  10022. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10023.  
  10024. ThingDebugView class
  10025.     instanceVariableNames: ''!
  10026.  
  10027.  
  10028. !ThingDebugView class methodsFor: 'instance creation'!
  10029.  
  10030. openOn: aThing
  10031.     "Open a new ThingDebugView on the given Thing."
  10032.  
  10033.     self
  10034.         openWithSubview:
  10035.             ((ThingDebugView new) model: (ThingDebug on: aThing))
  10036.         label: 'Debugger on ', aThing name.! !
  10037.  
  10038. Constraint subclass: #EqualityConstraint
  10039.     instanceVariableNames: ''
  10040.     classVariableNames: 'SharedMethods '
  10041.     poolDictionaries: ''
  10042.     category: 'ThingLabII-Constraints-Special'!
  10043. EqualityConstraint comment:
  10044. 'I am used to constrain two variable to contain the same value.'!
  10045.  
  10046.  
  10047. !EqualityConstraint methodsFor: 'initialize-release'!
  10048.  
  10049. ref: ref1 ref: ref2 strength: aSymbol
  10050.     "Initialize myself with the given strength between the two referenced parts."
  10051.  
  10052.     strength _ Strength of: aSymbol.
  10053.     symbols _ #(a b).
  10054.     self variables: (Array with: ref1 with: ref2).
  10055.     "initialize methods list shared by all instances"
  10056.     (SharedMethods isNil) ifTrue:
  10057.         [SharedMethods _ Array
  10058.             with: ((Method new)
  10059.                 codeString: 'a _ b';
  10060.                 block: [: vars | (vars at: 1) value: (vars at: 2) value. vars _ nil];
  10061.                 bindings: 'oi')
  10062.             with: ((Method new)
  10063.                 codeString: 'b _ a';
  10064.                 block: [: vars | (vars at: 2) value: (vars at: 1) value. vars _ nil];
  10065.                 bindings: 'io')].
  10066.     self methods: SharedMethods.
  10067.     whichMethod _ nil.
  10068.     self initializeFlags.! !
  10069. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10070.  
  10071. EqualityConstraint class
  10072.     instanceVariableNames: ''!
  10073.  
  10074.  
  10075. !EqualityConstraint class methodsFor: 'instance creation'!
  10076.  
  10077. ref: ref1 ref: ref2 strength: strength
  10078.     "Create a new equality constraint with the given strength equating the values referenced by ref1 and ref2. For example:
  10079.  
  10080.     EqualityConstraint
  10081.         ref: aThing->line.p1.y
  10082.         ref: aThing->line.p2.y
  10083.         strength: #required."
  10084.  
  10085.     ^(super new) ref: ref1 ref: ref2 strength: strength!
  10086.  
  10087. require: ref1 equals: ref2
  10088.     "Install a required EqualityConstraint between the given references."
  10089.  
  10090.     (self ref: ref1 ref: ref2 strength: #required) addConstraint.! !
  10091.  
  10092. Thing subclass: #PrimitiveThing
  10093.     instanceVariableNames: ''
  10094.     classVariableNames: ''
  10095.     poolDictionaries: ''
  10096.     category: 'ThingLabII-Things'!
  10097. PrimitiveThing comment:
  10098. 'I am an abstract class for primitive Things. Primitive Things cannot be structurally changed.'!
  10099.  
  10100.  
  10101. !PrimitiveThing methodsFor: 'initialize-release'!
  10102.  
  10103. initializeConstraints
  10104.     "Override this method to add constraints when initializing the prototype of a PrimitiveThing. This method is called after the structure of the Thing is initialized. By default, no constraints are added."!
  10105.  
  10106. initializeStructure
  10107.     "Override this method to initialize the part-whole structure when initializing the prototype of a PrimitiveThing. By default, no Thing subparts are created."!
  10108.  
  10109. initializeValues
  10110.     "Override this method to initialize part values when initializing the prototype of a PrimitiveThing. This method is called after the structure of the Thing is initialized and constraints have been added. By default, no initial values are provided."! !
  10111.  
  10112. !PrimitiveThing methodsFor: 'public-testing'!
  10113.  
  10114. isStructureModifiable
  10115.     "Primitive Things cannot be modified."
  10116.  
  10117.     ^false! !
  10118. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10119.  
  10120. PrimitiveThing class
  10121.     instanceVariableNames: ''!
  10122.  
  10123.  
  10124. !PrimitiveThing class methodsFor: 'class initialization'!
  10125.  
  10126. initialize
  10127.     "Initialize this PrimitiveThing."
  10128.  
  10129.     self initializePrimitive.! !
  10130.  
  10131. !PrimitiveThing class methodsFor: 'private-initialize-destroy'!
  10132.  
  10133. vaporize
  10134.     "Make this a noop, to avoid accidentally deleting primitive Things."! !
  10135.  
  10136.  
  10137. AbstractMethod subclass: #ModuleMethod
  10138.     instanceVariableNames: 'module isPossibleSel executeSel propagateSel '
  10139.     classVariableNames: ''
  10140.     poolDictionaries: ''
  10141.     category: 'ThingLabII-Constraints'!
  10142. ModuleMethod comment:
  10143. 'I represent methods for compiled ModuleThings. I have a pointer to the ModuleThing instance and a bunch of selectors to perform various operations on that ModuleThing in order to plan for and perform constraint satisfaction.
  10144.  
  10145. Instance variables (in addition to those inherited):
  10146.  
  10147.     owner...            my ModuleThing
  10148.     executeSel...        selector to compute the values of my outputs
  10149.      checkSel...        selector to compute if I am an appropriate method
  10150.     walkSel...        selector to compute the walkabout strengths of my outputs
  10151.     ancestorSel...        selector to compute the ancestors of my outputs
  10152. '!
  10153.  
  10154.  
  10155. !ModuleMethod methodsFor: 'initialize-release'!
  10156.  
  10157. destroy
  10158.     "Break potential cycles."
  10159.  
  10160.     module _ nil.
  10161.     super destroy.!
  10162.  
  10163. module: owningModule codeString: aString bindings: bindingArray isPossible: isPossibleSelector execute: executeSelector propagate: propagateSelector
  10164.     "Initialize myself."
  10165.  
  10166.     module _ owningModule.
  10167.     codeString _ aString.
  10168.     bindings _ bindingArray.
  10169.     isPossibleSel _ isPossibleSelector asSymbol.
  10170.     executeSel _ executeSelector asSymbol.
  10171.     propagateSel _ propagateSelector asSymbol.! !
  10172.  
  10173. !ModuleMethod methodsFor: 'DeltaBlue'!
  10174.  
  10175. execute: refList
  10176.     "Execute myself to enforce my constraint. Do this by executing the method compiled for that purpose. refList is ignored."
  10177.  
  10178.     module perform: executeSel.!
  10179.  
  10180. isPossibleMethodGiven: constraintStrength
  10181.     "Answer true if I am a possible method given the current walkabout strengths of my variables. Compute the answer by executing the method compiled for that purpose."
  10182.  
  10183.     ^module perform: isPossibleSel!
  10184.  
  10185. updateOutputsIn: thingDatas for: myConstraint stay: stayFlag
  10186.     "Update the walkabout strengths and stay flags for all my outputs and answer the output ThingDatas. Do this by executing the method compiled for that purpose."
  10187.  
  10188.     module perform: propagateSel.
  10189.     ^myConstraint outDatas! !
  10190.  
  10191. !ModuleMethod methodsFor: 'cloning'!
  10192.  
  10193. cloneWith: cloneDictionary for: ignored
  10194.     "Make a clone of myself using the mapping given by cloneDictionary."
  10195.  
  10196.     | myClone |
  10197.     myClone _ self shallowCopy.
  10198.     myClone module: (cloneDictionary at: module).
  10199.     ^myClone!
  10200.  
  10201. module: aModuleThing
  10202.     "Used in cloning."
  10203.  
  10204.     module _ aModuleThing.! !
  10205. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10206.  
  10207. ModuleMethod class
  10208.     instanceVariableNames: ''!
  10209.  
  10210.  
  10211. !ModuleMethod class methodsFor: 'instance creation'!
  10212.  
  10213. module: owningModule codeString: aString bindings: bindingArray isPossible: isPossibleSelector execute: executeSelector propagate: propagateSelector
  10214.     "Answer a new, initialized instance."
  10215.  
  10216.     ^self new
  10217.         module: owningModule
  10218.         codeString: aString
  10219.         bindings: bindingArray
  10220.         isPossible: isPossibleSelector
  10221.         execute: executeSelector
  10222.         propagate: propagateSelector! !
  10223.  
  10224. BasicThingView subclass: #ThingModuleView
  10225.     instanceVariableNames: 'constructorView '
  10226.     classVariableNames: ''
  10227.     poolDictionaries: ''
  10228.     category: 'ThingLabII-UI-Thing Views'!
  10229.  
  10230.  
  10231. !ThingModuleView methodsFor: 'initialize-release'!
  10232.  
  10233. initialize
  10234.  
  10235.     super initialize.
  10236.     constructorView _ nil.! !
  10237.  
  10238. !ThingModuleView methodsFor: 'controller access'!
  10239.  
  10240. defaultControllerClass
  10241.  
  10242.     ^ThingModuleController! !
  10243.  
  10244. !ThingModuleView methodsFor: 'access'!
  10245.  
  10246. constructorView
  10247.  
  10248.     ^constructorView!
  10249.  
  10250. constructorView: aView
  10251.  
  10252.     constructorView _ aView.!
  10253.  
  10254. model: aThingAdaptor
  10255.  
  10256.     super model: aThingAdaptor.
  10257.     model clearSelection.
  10258.     model thing class externalParts do:
  10259.         [: part | model select: (model thing perform: part)].! !
  10260.  
  10261. !ThingModuleView methodsFor: 'displaying'!
  10262.  
  10263. computeBackground
  10264.     "Compute the backgroundForm and the two lists, visibleForeground and selectedForeground. These are used by the 'displayFeedback' and 'displayFeedbackWithBox:width:' operations."
  10265.  
  10266.     | viewExtent viewOrigin clipBox |
  10267.     viewExtent _ enclosingRect extent max: self insetDisplayBox extent.
  10268.     backgroundForm _ Form extent: viewExtent.
  10269.     scratchForm _ Form extent: viewExtent.
  10270.     viewOrigin _ self viewOrigin.
  10271.     clipBox _ backgroundForm computeBoundingBox.
  10272.  
  10273.     "draw and gray-out the internal glyphs"
  10274.     self internalGlyphsDo:
  10275.         [: glyph |
  10276.          glyph
  10277.             displayOn: backgroundForm
  10278.             at: viewOrigin clippingBox: clipBox].
  10279.     backgroundForm fill: clipBox rule: Form erase mask: Form gray.
  10280.  
  10281.     "draw the border and external glyphs"
  10282.     self displayBorderOn: backgroundForm at: viewOrigin clippingBox: clipBox.
  10283.     self externalGlyphsDo:
  10284.         [: glyph |
  10285.          glyph
  10286.             displayOn: backgroundForm
  10287.             at: viewOrigin clippingBox: clipBox].
  10288.  
  10289.     "nothing is changing"
  10290.     visibleForeground _ OrderedCollection new.
  10291.     selectedForeground _ OrderedCollection new.!
  10292.  
  10293. externalGlyphsDo: aBlock
  10294.  
  10295.     (model visibleGlyphs) do:
  10296.         [: g |
  10297.          (model selected includes: g) ifTrue:
  10298.             [aBlock value: g]].!
  10299.  
  10300. internalGlyphsDo: aBlock
  10301.  
  10302.     (model visibleGlyphs) do:
  10303.         [: g |
  10304.          ((model selected includes: g) not) ifTrue:
  10305.             [aBlock value: g]].! !
  10306.  
  10307. GestureController subclass: #SceneController
  10308.     instanceVariableNames: 'myMenu lastMenuItem doneFlag '
  10309.     classVariableNames: ''
  10310.     poolDictionaries: ''
  10311.     category: 'ThingLabII-UI-Framework'!
  10312. SceneController comment:
  10313. 'This is the controller class for SceneViews. It supports gestures for scrolling, click-selection, and area selection of scene glyphs.'!
  10314.  
  10315.  
  10316. !SceneController methodsFor: 'initialize-release'!
  10317.  
  10318. initialize
  10319.  
  10320.     super initialize.
  10321.     myMenu _ CustomMenu new.
  10322.     lastMenuItem _ nil.
  10323.     doneFlag _ false.! !
  10324.  
  10325. !SceneController methodsFor: 'control defaults'!
  10326.  
  10327. controlActivity
  10328.     "Process user mouse and keyboard activity."
  10329.  
  10330.     (sensor keyboardPressed) ifTrue: [^self readKeyboard].
  10331.     (sensor yellowButtonPressed) ifTrue: [^self menuActivity].
  10332.     (sensor redButtonPressed) ifTrue: [^super possibleClickAt: sensor cursorPoint].!
  10333.  
  10334. isControlActive
  10335.  
  10336.     ^self viewHasCursor
  10337.         & sensor blueButtonPressed not
  10338.         & self done not!
  10339.  
  10340. isControlWanted
  10341.  
  10342.     ^self viewHasCursor & sensor blueButtonPressed not! !
  10343.  
  10344. !SceneController methodsFor: 'access'!
  10345.  
  10346. done
  10347.     "Should I give up control?"
  10348.  
  10349.     ^doneFlag!
  10350.  
  10351. done: aBoolean
  10352.     "A flag is maintained to allow me to gracefully give up control (see isControlActive and isControlWanted) when switching between View/Controller pairs within the same top view."
  10353.  
  10354.     doneFlag _ aBoolean.! !
  10355.  
  10356. !SceneController methodsFor: 'gestures'!
  10357.  
  10358. clickAt: aPoint
  10359.     "If the mouse is clicked over a glyph that wants mouse input and we are in 'operate' mode, pass the mouse to it. Otherwise, select the glyph under aPoint. If the shift key is depressed, the glyph's inclusion in the selection is toggled: that is, it is added to the selection if it is not currently selected and removed from the selection if it is currently selected."
  10360.  
  10361.     "first, try to process mouse input for the glyph at aPoint"
  10362.     (self processMouseAt: aPoint) ifTrue: [^self].
  10363.  
  10364.     "if that fails, do select operation"
  10365.     self selectAt: aPoint toggleFlag: (sensor leftShiftDown).
  10366.     view displayScene.!
  10367.  
  10368. doubleClickAt: aPoint
  10369.     "Handle a double-click action by selecting everything."
  10370.  
  10371.     self selectAll.
  10372.     sensor waitNoButton.!
  10373.  
  10374. dragAt: aPoint
  10375.     "Handle a drag action. If aPoint is over a glyph that is interested in mouse actions, let that glyph handle the mouse. Otherwise, move or scroll depending on whether or not the given point is over a selectable glyph or not."
  10376.  
  10377.     | glyph |
  10378.     "first, try to process mouse input for the glyph at aPoint"
  10379.     (self processMouseAt: aPoint) ifTrue: [^self].
  10380.  
  10381.     "if that fails, handle the normal move-or-scroll situation"
  10382.     glyph _ self glyphAt: aPoint.
  10383.     (glyph notNil)
  10384.         ifTrue:
  10385.             ["if the glyph is not in the selection, select it"
  10386.              (model selected includes: glyph) ifFalse:
  10387.                 [self selectAt: aPoint toggleFlag: (sensor leftShiftDown)].
  10388.              view displayScene.
  10389.              self moveAt: aPoint]
  10390.         ifFalse: [self scrollAt: aPoint].!
  10391.  
  10392. processMouseAt: aPoint
  10393.     "If the given point is over a glyph that is interested in mouse actions, let that glyph handle the mouse and answer true. Otherwise, answer false."
  10394.  
  10395.     | mouseGlyph |
  10396.     mouseGlyph _ self mouseGlyphAt: aPoint.
  10397.     (mouseGlyph notNil)
  10398.         ifTrue: [self passMouseTo: mouseGlyph. ^true]
  10399.         ifFalse: [^false].!
  10400.  
  10401. sweepAt: aPoint
  10402.     "First, try to pass the mouse to any glyphs under aPoint that want it. If there aren't any mouse input glyphs by there is a selectable glyph under aPoint, then select it and drag the selected glyphs. Otherwise, handle the sweep gesture by doing an area-select. If the shift key is down, then toggle select all enclosed glyphs. Otherwise, clear the selection first."
  10403.  
  10404.     "first, try to process mouse input for the glyph at aPoint"
  10405.     (self processMouseAt: aPoint) ifTrue: [^self].
  10406.  
  10407.     "if that fails, handle the normal move-or-area-select situation"
  10408.     ((self glyphAt: aPoint) notNil)    "check for a drag situation"
  10409.         ifTrue: [self dragAt: aPoint]
  10410.         ifFalse:
  10411.             [self
  10412.                 selectAreaAt: aPoint
  10413.                 toggleFlag: (sensor leftShiftDown)].! !
  10414.  
  10415. !SceneController methodsFor: 'menu handling'!
  10416.  
  10417. argument
  10418.     "Answer the argument for unary operation from the model's selection. There must be exactly one object selected. If so, answer it. Otherwise, answer nil."
  10419.  
  10420.     (model selected size == 1)
  10421.         ifTrue: [^model selected asOrderedCollection first]
  10422.         ifFalse: [^nil].!
  10423.  
  10424. menuActivity
  10425.     "Present the yellow button menu and determine which menu item, if any, the user selected. If an item was selected, then send that message to the object designated as the menu message receiver. Remember the menu item across menu invocations."
  10426.  
  10427.     | menu item |
  10428.     menu _ self yellowButtonMenu: (sensor leftShiftDown).
  10429.     (menu isNil) ifTrue: [^self].
  10430.  
  10431.     item _ menu invoke: lastMenuItem.
  10432.     lastMenuItem _ item.
  10433.     (item notNil) ifTrue: [self perform: item].!
  10434.  
  10435. yellowButtonMenu: debugging
  10436.     "Answer my yellow-button menu, constructed by sending myself the message 'addMenuItems: debugging.' Items are appended to the CustomMenu myMenu; this allows subclasses to augment the menu provided  by their superclass without the maintainance headache of copying the menu creation code into the subclass."
  10437.  
  10438.     myMenu _ CustomMenu new.
  10439.     self addMenuItems: debugging.
  10440.     ^myMenu! !
  10441.  
  10442. !SceneController methodsFor: 'menu operations'!
  10443.  
  10444. addMenuItems: debugging
  10445.     "Answer my yellow-button menu given the current selection and possibly some other view or controller state. The goal is to present in the menu only those possibilities which are legal commands at this juncture. If debugging is true, present a additional options which might be useful to implementors and other gurus."
  10446.  
  10447.     myMenu add: ' scroll ' action: #scroll.
  10448.     myMenu add: ' area ' action: #selectArea.
  10449.     myMenu addLine.
  10450.     myMenu add: ' all ' action: #selectAll.
  10451.     (model selected size > 0) ifTrue:
  10452.         [myMenu add: ' none ' action: #clearSelection].
  10453.     myMenu addLine.!
  10454.  
  10455. clearSelection
  10456.     "Unselect everything."
  10457.  
  10458.     model clearSelection.
  10459.     view displayScene.!
  10460.  
  10461. scroll
  10462.     "Wait for the mouse button to be pressed, then scroll."
  10463.  
  10464.     Cursor hand showWhile: [sensor waitButton].
  10465.     self scrollAt: sensor cursorPoint.!
  10466.  
  10467. selectAll
  10468.     "Select all selectable glyphs."
  10469.  
  10470.     model clearSelection.
  10471.     model selectableGlyphs do: [: g | model select: g].
  10472.     view displayScene.!
  10473.  
  10474. selectArea
  10475.     "Select everything in a rectangular area specified using the mouse. If the shift key is down, toggle select everything in the area."
  10476.  
  10477.     Cursor origin showWhile: [sensor waitButton].
  10478.     self selectAreaAt: (sensor cursorPoint) toggleFlag: (sensor leftShiftDown).! !
  10479.  
  10480. !SceneController methodsFor: 'direct manipulation'!
  10481.  
  10482. adjustedPoint: aPoint
  10483.     "Answer a point (in view coordinates) that is as close to aPoint (in screen coordinates) as possible."
  10484.  
  10485.     | borderBox adjustedPoint |
  10486.     borderBox _ view insetDisplayBox insetBy: 5.
  10487.     adjustedPoint _ aPoint copy.
  10488.     (aPoint x < borderBox left) ifTrue: [adjustedPoint x: borderBox left].
  10489.     (aPoint x > borderBox right) ifTrue: [adjustedPoint x: borderBox right].
  10490.     (aPoint y < borderBox top) ifTrue: [adjustedPoint y: borderBox top].
  10491.     (aPoint y > borderBox bottom) ifTrue: [adjustedPoint y: borderBox bottom].    
  10492.     ^view displayToModelPoint: adjustedPoint!
  10493.  
  10494. adjustOffsetForSelArea: aPoint
  10495.     "If aPoint (in screen coordinates) is outside my inset display box, try to scroll the view in that direction."
  10496.  
  10497.     | box pX pY left right top bottom new |
  10498.     box _ view insetDisplayBox.
  10499.     (box containsPoint: aPoint) ifTrue: [^self].
  10500.     pX _ aPoint x.
  10501.     pY _ aPoint y.
  10502.     left _ box left.
  10503.     right _ box right.
  10504.     top _ box top.
  10505.     bottom _ box bottom.
  10506.     new _ view scrollOffset.
  10507.     (pX < left) ifTrue: [new x: (new x + left - pX)].
  10508.     (pX > right) ifTrue: [new x: (new x + right - pX)].
  10509.     (pY < top) ifTrue: [new y: (new y + top - pY)].
  10510.     (pY > bottom) ifTrue: [new y: (new y + bottom - pY)].
  10511.     view scrollOffset: new.!
  10512.  
  10513. glyphAt: aPoint
  10514.     "Answer the selectable glyph at aPoint or nil if there isn't one."
  10515.  
  10516.     | adjustedPoint pointX pointY box |
  10517.     adjustedPoint _ view displayToModelPoint: aPoint.
  10518.     pointX _ adjustedPoint x.
  10519.     pointY _ adjustedPoint y.
  10520.     model selectableGlyphs do:
  10521.         [: glyph |
  10522.          box _ glyph boundingBox.
  10523.          (box top <= pointY) ifTrue:
  10524.             [(box bottom >= pointY) ifTrue:
  10525.                 [(box left <= pointX) ifTrue:
  10526.                     [(box right >= pointX) ifTrue:
  10527.                         [(glyph containsPoint: adjustedPoint) ifTrue:
  10528.                             [^glyph]]]]]].
  10529.     ^nil        "no glyph found"!
  10530.  
  10531. moveAt: aPoint
  10532.     "Drag all selected glyphs."
  10533.  
  10534.     | movingParts relativePositions point oldPoint |
  10535.     movingParts _ model selected asOrderedCollection.
  10536.     model moveToFront: movingParts.
  10537.     relativePositions _ movingParts collect: [: p | p location - aPoint].
  10538.     view computeBackground.
  10539.     [sensor redButtonPressed] whileTrue:
  10540.         [point _ sensor cursorPoint.
  10541.          (oldPoint ~= sensor cursorPoint) ifTrue:
  10542.             [movingParts
  10543.                 with: relativePositions
  10544.                 do: [: p : relPos | p location: (relPos + point)].
  10545.              view displayFeedback]].
  10546.     view computeEnclosingRectangle.
  10547.     view displayView.!
  10548.  
  10549. scrollAt: aPoint
  10550.     "As the user moves the cursor, change the offset of my model to scroll the view."
  10551.  
  10552.     | limits relOffset hotRect ratio lastPoint newPoint |
  10553.     limits _ view scrollOffsetLimits.
  10554.     Cursor hand showWhile:
  10555.         [view computeBackground.
  10556.          relOffset _
  10557.             (view scrollOffset * -40) / (limits extent max: (1@1)).
  10558.          hotRect _ (aPoint + relOffset - (40@40)) extent: 40@40.
  10559.          ratio _ limits extent / hotRect extent.
  10560.          lastPoint _ -1@-1.
  10561.          [sensor redButtonPressed] whileTrue:
  10562.              [newPoint _ sensor cursorPoint.
  10563.              (newPoint ~= lastPoint) ifTrue:
  10564.                 [view scrollOffset:
  10565.                     (ratio * (newPoint - hotRect corner)) rounded.
  10566.                   view displayFeedback.
  10567.                  lastPoint _ newPoint]]].!
  10568.  
  10569. selectAreaAt: aPoint toggleFlag: toggleFlag
  10570.     "As the user moves the cursor, draw a selection rectangle, scrolling if the mouse leaves my view. When the red button is released, select all selectable glyphs inside the selection rectangle."
  10571.  
  10572.     | origin corner selectionRect viewBox done newPoint lastPoint |
  10573.     toggleFlag ifFalse: [model clearSelection].
  10574.     origin _ self adjustedPoint: aPoint.
  10575.     selectionRect _ origin extent: 0@0.
  10576.     view computeBackground.
  10577.     viewBox _ view insetDisplayBox.
  10578.     lastPoint _ -1@-1.
  10579.     done _ false.     "do the loop at least once"
  10580.     [done] whileFalse:
  10581.          [newPoint _ sensor cursorPoint.
  10582.          ((newPoint ~= lastPoint) or: [(viewBox containsPoint: newPoint) not]) ifTrue:
  10583.             [self adjustOffsetForSelArea: newPoint.
  10584.              corner _ self adjustedPoint: newPoint.
  10585.              selectionRect _ Rectangle
  10586.                 origin: (origin min: corner)
  10587.                 extent: ((origin - corner) abs).
  10588.              view displayFeedbackWithBox: selectionRect width: 1.
  10589.              lastPoint _ newPoint].
  10590.          done _ sensor anyButtonPressed not].
  10591.  
  10592.     model selectableGlyphs do:
  10593.         [: p |
  10594.          (p intersects: selectionRect)
  10595.             ifTrue:
  10596.                 [toggleFlag
  10597.                     ifTrue: [model toggleSelect: p]
  10598.                     ifFalse: [model select: p]]].
  10599.     view displayScene.!
  10600.  
  10601. selectAt: aPoint toggleFlag: toggleFlag
  10602.     "Select the glyph at aPoint. If toggleFlag is true, add/remove the glyph to/from the selection. Otherwise add the glyph. If aPoint is not over any glyph then clear the selection."
  10603.  
  10604.     | glyph |
  10605.     glyph _ self glyphAt: aPoint.
  10606.     (glyph notNil)
  10607.         ifTrue:
  10608.             [((model selected includes: glyph) not & toggleFlag not)
  10609.                 ifTrue: [model clearSelection].
  10610.              toggleFlag
  10611.                 ifTrue: [model toggleSelect: glyph]
  10612.                 ifFalse: [model select: glyph]]
  10613.         ifFalse: [model clearSelection].! !
  10614.  
  10615. !SceneController methodsFor: 'keyboard'!
  10616.  
  10617. readKeyboard
  10618.     "Keystrokes are sent to all selected Things that are interested in keyboard input."
  10619.  
  10620.     | interested char |
  10621.     interested _ model selected select:
  10622.         [: thing |
  10623.          (thing wantsKeystrokes) and: [model inputGlyphs includes: thing]].
  10624.  
  10625.     [sensor keyboardPressed] whileTrue:
  10626.         [self resetTimer.
  10627.          char _ sensor keyboard.
  10628.          interested do:
  10629.             [: thing | thing handleKeystroke: char view: view].
  10630.          [(self timeOut: 100) | sensor keyboardPressed] whileFalse:
  10631.             ["wait a bit in case there is another character"]].
  10632.     view displayScene.! !
  10633.  
  10634. !SceneController methodsFor: 'mouse'!
  10635.  
  10636. adjustedCursorPoint
  10637.     "Answer the cursor point in adjusted view coordinates."
  10638.  
  10639.     ^view displayToModelPoint: sensor cursorPoint!
  10640.  
  10641. mouseGlyphAt: aPoint
  10642.     "Answer the mouse glyph at aPoint or nil if there isn't one."
  10643.  
  10644.     | adjustedPoint |
  10645.     adjustedPoint _ view displayToModelPoint: aPoint.
  10646.     model inputGlyphs reverseDo:
  10647.         [: g |
  10648.          ((g wantsMouse) and:
  10649.            [g containsPoint: adjustedPoint]) ifTrue:
  10650.             [^g]].
  10651.  
  10652.     ^nil    "no mouse input glyph found"!
  10653.  
  10654. passMouseTo: aGlyph
  10655.     "Allow the given glyph to handle a mouse interaction. It is assumed that the glyph wants the mouse."
  10656.  
  10657.     aGlyph handleMouseDown: self adjustedCursorPoint view: view.
  10658.     aGlyph handleMouseMove: self adjustedCursorPoint view: view.        "do at least once"
  10659.     [sensor anyButtonPressed] whileTrue:
  10660.         [aGlyph handleMouseMove: self adjustedCursorPoint view: view].
  10661.     aGlyph handleMouseUp: self adjustedCursorPoint view: view.
  10662.     view displayScene.! !
  10663.  
  10664. Constraint subclass: #YMouseConstraint
  10665.     instanceVariableNames: 'yOffset '
  10666.     classVariableNames: ''
  10667.     poolDictionaries: ''
  10668.     category: 'ThingLabII-Constraints-Special'!
  10669. YMouseConstraint comment:
  10670. 'I am used to relate a variable to the current y-coordinate of the mouse. I contain an offset to normalize the coordinate system to one convenient for the target variable. I have only one method with no inputs and one output.'!
  10671.  
  10672.  
  10673. !YMouseConstraint methodsFor: 'initialize-release'!
  10674.  
  10675. ref: ref strength: aSymbol offset: aNumber
  10676.     "Initialize myself with the given reference, strength, and y-offset."
  10677.  
  10678.     strength _ Strength of: aSymbol.
  10679.     symbols _ #(y).
  10680.     self variables: (Array with: ref).
  10681.     self methods: (Array with:
  10682.         ((Method new)
  10683.             codeString: '"mouseY"';
  10684.             block:
  10685.                 [: vars |
  10686.                  (vars at: 1) value: (Sensor mousePoint y + yOffset).
  10687.                  vars _ nil];
  10688.             bindings: 'o')).
  10689.     whichMethod _ nil.
  10690.     self initializeFlags.
  10691.     yOffset _ aNumber.! !
  10692.  
  10693. !YMouseConstraint methodsFor: 'queries'!
  10694.  
  10695. isInput
  10696.     "I depend on the state of the mouse."
  10697.  
  10698.     ^true! !
  10699. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10700.  
  10701. YMouseConstraint class
  10702.     instanceVariableNames: ''!
  10703.  
  10704.  
  10705. !YMouseConstraint class methodsFor: 'instance creation'!
  10706.  
  10707. ref: ref strength: strength offset: yOffset
  10708.     "Create a YMouse constraint on the referenced variable. For example:
  10709.  
  10710.     YMouseConstraint
  10711.         ref: myPoint->#y
  10712.         strength: #preferred
  10713.         offset: (Sensor cursorPoint y)."
  10714.  
  10715.     ^(super new) ref: ref strength: strength offset: yOffset! !
  10716.  
  10717. Constraint subclass: #XMouseConstraint
  10718.     instanceVariableNames: 'xOffset '
  10719.     classVariableNames: ''
  10720.     poolDictionaries: ''
  10721.     category: 'ThingLabII-Constraints-Special'!
  10722. XMouseConstraint comment:
  10723. 'I am used to relate a variable to the current x-coordinate of the mouse. I contain an offset to normalize the coordinate system to one convenient for the target variable. I have only one method with no inputs and one output.'!
  10724.  
  10725.  
  10726. !XMouseConstraint methodsFor: 'initialize-release'!
  10727.  
  10728. ref: ref strength: aSymbol offset: aNumber
  10729.     "Initialize myself with the given reference, strength, and x-offset."
  10730.  
  10731.     strength _ Strength of: aSymbol.
  10732.     symbols _ #(x).
  10733.     self variables: (Array with: ref).
  10734.     self methods: (Array with:
  10735.         ((Method new)
  10736.             codeString: '"mouseX"';
  10737.             block:
  10738.                 [: vars |
  10739.                  (vars at: 1) value: (Sensor mousePoint x + xOffset).
  10740.                  vars _ nil];
  10741.             bindings: 'o')).
  10742.     whichMethod _ nil.
  10743.     self initializeFlags.
  10744.     xOffset _ aNumber.! !
  10745.  
  10746. !XMouseConstraint methodsFor: 'queries'!
  10747.  
  10748. isInput
  10749.     "I depend on the state of the mouse."
  10750.  
  10751.     ^true! !
  10752. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10753.  
  10754. XMouseConstraint class
  10755.     instanceVariableNames: ''!
  10756.  
  10757.  
  10758. !XMouseConstraint class methodsFor: 'instance creation'!
  10759.  
  10760. ref: ref strength: strength offset: aNumber
  10761.     "Create an XMouse constraint on the referenced variable. For example:
  10762.  
  10763.     XMouseConstraint
  10764.         ref: myPoint->#x
  10765.         strength: #preferred
  10766.         offset: (Sensor cursorPoint x)."
  10767.  
  10768.     ^(super new) ref: ref strength: strength offset: aNumber! !
  10769.  
  10770. Controller subclass: #ThingLabIIControlPanel
  10771.     instanceVariableNames: 'bigLabelSwitch gridXview gridYview editPreferredSwitch '
  10772.     classVariableNames: 'BigLabelFlag Where '
  10773.     poolDictionaries: ''
  10774.     category: 'ThingLabII-UI-Support'!
  10775.  
  10776.  
  10777. !ThingLabIIControlPanel methodsFor: 'initialize-release'!
  10778.  
  10779. addEditLevelSwitches: topView
  10780.     "Add switches to control the strength of user edits."
  10781.  
  10782.     | toggle labelView preferredSWView editRequiredSwitch requiredSWView |
  10783.     toggle _ Model new.
  10784.     labelView _ (FormView new)
  10785.                 model: 'Edit Strength:' asParagraph asForm;
  10786.                 borderWidth: 0;
  10787.                 controller: NoController new.
  10788.     editPreferredSwitch _ (ThingLabII editStrength == #preferred)
  10789.             ifTrue: [OneOnSwitch newOn]
  10790.             ifFalse: [OneOnSwitch newOff].
  10791.     editRequiredSwitch _ (ThingLabII editStrength == #preferred)
  10792.             ifTrue: [OneOnSwitch newOff]
  10793.             ifFalse: [OneOnSwitch newOn].
  10794.     editPreferredSwitch connection: toggle.
  10795.     editRequiredSwitch connection: toggle.
  10796.     preferredSWView _ (SwitchView new)
  10797.             model: editPreferredSwitch;
  10798.             label: 'preferred' asParagraph centered;
  10799.             borderWidth: 1.
  10800.     requiredSWView _ (SwitchView new)
  10801.             model: editRequiredSwitch;
  10802.             label: 'required' asParagraph centered;
  10803.             borderWidth: 1.
  10804.     topView
  10805.         addSubView: labelView align: 0@0 with: 15@58;
  10806.         addSubView: preferredSWView align: 0@0 with: 107@60;
  10807.         addSubView: requiredSWView align: 0@0 with: 168@60.!
  10808.  
  10809. addGridSettings: topView
  10810.     "Add controls to set the PartBin grid."
  10811.  
  10812.     | gridXLabel gridYLabel |
  10813.     gridXLabel _ (FormView new)
  10814.         model: 'Parts Bin GridX:' asParagraph asForm;
  10815.         borderWidth: 0;
  10816.         controller: NoController new.
  10817.     gridXview _ (StringHolderView new)
  10818.         model: ((StringHolder new) contents: (PartsBin gridX printString));
  10819.         window: (0@0 extent: 32@19);
  10820.         borderWidth: 1.
  10821.     gridYLabel _ (FormView new)
  10822.         model: 'GridY:' asParagraph asForm;
  10823.         borderWidth: 0;
  10824.         controller: NoController new.
  10825.     gridYview _ (StringHolderView new)
  10826.         model: ((StringHolder new) contents: (PartsBin gridY printString));
  10827.         window: (0@0 extent: 32@19);
  10828.         borderWidth: 1.
  10829.     topView
  10830.         addSubView: gridXLabel align: 0@0 with: 15@95;
  10831.         addSubView: gridXview align: 0@0 with: 105@95;
  10832.         addSubView: gridYLabel align: 0@0 with: 145@95;
  10833.         addSubView: gridYview align: 0@0 with: 185@95.!
  10834.  
  10835. addLabelSizeSwitches: topView
  10836.     "Add switches to control the size of the labels for Thinglab windows."
  10837.  
  10838.     | toggle labelView bigSWView smallSwitch smallSWView |
  10839.     toggle _ Model new.
  10840.     labelView _ (FormView new)
  10841.                 model: 'Label Size:' asParagraph asForm;
  10842.                 borderWidth: 0;
  10843.                 controller: NoController new.
  10844.     bigLabelSwitch _ (BigLabelFlag)
  10845.             ifTrue: [OneOnSwitch newOn]
  10846.             ifFalse: [OneOnSwitch newOff].
  10847.     bigLabelSwitch connection: toggle.
  10848.     bigSWView _ (SwitchView new)
  10849.             model: bigLabelSwitch;
  10850.             label: 'big' asParagraph centered;
  10851.             borderWidth: 1.
  10852.     smallSwitch _ (BigLabelFlag)
  10853.             ifTrue: [OneOnSwitch newOff]
  10854.             ifFalse: [OneOnSwitch newOn].
  10855.     smallSwitch connection: toggle.
  10856.     smallSWView _ (SwitchView new)
  10857.             model: smallSwitch;
  10858.             label: 'small' asParagraph centered;
  10859.             borderWidth: 1.
  10860.     topView
  10861.         addSubView: labelView align: 0@0 with: 15@23;
  10862.         addSubView: bigSWView align: 0@0 with: 107@25;
  10863.         addSubView: smallSWView align: 0@0 with: 133@25.!
  10864.  
  10865. addMenu: topView
  10866.     "Adds an invisible sub-view whose controller is myself. This allows me to support the 'the application menu is available from the center of the top view's label' scheme, which tries to send the #menuActivity message to the first subview. This method should be executed first to ensure that this is the first sub-view."
  10867.  
  10868.     | firstSubview |
  10869.     firstSubview _ (FormView new)
  10870.         model: (Form extent: 0@0);
  10871.         borderWidth: 0;
  10872.         controller: self.
  10873.     topView
  10874.         addSubView: firstSubview align: 0@0 with: 0@0.!
  10875.  
  10876. buildInside: aTopView
  10877.     "Set up my controls within the given view."
  10878.  
  10879.     self addMenu: aTopView.    "this should be done first"
  10880.     self addGridSettings: aTopView.
  10881.     self addEditLevelSwitches: aTopView.
  10882.     self addLabelSizeSwitches: aTopView.!
  10883.  
  10884. release
  10885.  
  10886.     super release.
  10887.     gridXview release.
  10888.     gridYview release.
  10889.     bigLabelSwitch release.
  10890.     editPreferredSwitch release.
  10891.     gridXview _ nil.
  10892.     gridYview _ nil.
  10893.     bigLabelSwitch _ nil.
  10894.     editPreferredSwitch _ nil.! !
  10895.  
  10896. !ThingLabIIControlPanel methodsFor: 'menu messages'!
  10897.  
  10898. applySettings
  10899.     "Apply the currently displayed settings."
  10900.  
  10901.     BigLabelFlag _ bigLabelSwitch isOn.
  10902.     (editPreferredSwitch isOn)
  10903.         ifTrue: [ThingLabII editStrength: #preferred]
  10904.         ifFalse: [ThingLabII editStrength: #required].
  10905.     gridXview controller accept.
  10906.     gridYview controller accept.
  10907.     PartsBin gridX: (gridXview getContents asString asNumber).
  10908.     PartsBin gridY: (gridYview getContents asString asNumber).!
  10909.  
  10910. cancelSettings
  10911.     "Undo changes to the currently displayed settings. This is done by removing all subview and rebuilding them, resetting the settings of the controls in the process."
  10912.  
  10913.     | topView |
  10914.     topView _ view topView.
  10915.     topView deEmphasize.
  10916.     topView removeSubViews.
  10917.     self buildInside: topView.
  10918.     topView displaySubViews.
  10919.     topView emphasize.!
  10920.  
  10921. menuActivity
  10922.     "Handle my menu."
  10923.  
  10924.     | action |
  10925.     action _ (PopUpMenu labels: 'done\apply\cancel' withCRs) startUp.
  10926.     (action == 1) ifTrue: [self applySettings. view topView controller close].
  10927.     (action == 2) ifTrue: [self applySettings].
  10928.     (action == 3) ifTrue: [self cancelSettings].! !
  10929. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10930.  
  10931. ThingLabIIControlPanel class
  10932.     instanceVariableNames: ''!
  10933.  
  10934.  
  10935. !ThingLabIIControlPanel class methodsFor: 'class initialization'!
  10936.  
  10937. initialize
  10938.     "Reset the initial location of the control panel."
  10939.     "ThingLabIIControlPanel initialize"
  10940.  
  10941.     Where _ 140@100.
  10942.     BigLabelFlag _ true.! !
  10943.  
  10944. !ThingLabIIControlPanel class methodsFor: 'instance creation'!
  10945.  
  10946. open
  10947.     "ThingLabIIControlPanel open"
  10948.  
  10949.     | panelRect controller topView |
  10950.     panelRect _ 0@0 extent: 235@135.
  10951.     controller _ (SpecialSystemController new) fromHolder: self.
  10952.     topView _ SpecialSystemView
  10953.         model: nil
  10954.         label: 'ThingLabII Control Panel'
  10955.         minimumSize: panelRect extent.
  10956.     topView
  10957.         maximumSize: panelRect extent;
  10958.         window: panelRect viewport: panelRect;
  10959.         controller: controller.
  10960.     self new buildInside: topView.
  10961.     controller openDisplayAt: Where.! !
  10962.  
  10963. !ThingLabIIControlPanel class methodsFor: 'accessing'!
  10964.  
  10965. bigLabelFlag
  10966.  
  10967.     ^BigLabelFlag!
  10968.  
  10969. lastFrame: aRectangle
  10970.     "Record the last position of the control panel so we can open it there next time."
  10971.  
  10972.     Where _ aRectangle center.! !
  10973.  
  10974.  
  10975. SceneController subclass: #ThingModuleController
  10976.     instanceVariableNames: ''
  10977.     classVariableNames: ''
  10978.     poolDictionaries: ''
  10979.     category: 'ThingLabII-UI-Thing Views'!
  10980.  
  10981.  
  10982. !ThingModuleController methodsFor: 'menu operations'!
  10983.  
  10984. addMenuItems: debugging
  10985.  
  10986.     super addMenuItems: debugging.
  10987.     myMenu add: ' compile ' action: #compile.
  10988.     myMenu add: ' cancel ' action: #cancel.!
  10989.  
  10990. cancel
  10991.     "Go back to the ConstructionView from whence I came..."
  10992.  
  10993.     | externalParts topView |
  10994.     "remember the external parts"
  10995.     externalParts _ 
  10996.         (model selected) collect:
  10997.             [: part | (part allTopParentPaths first) first].
  10998.     (model thing class) externalParts: externalParts asOrderedCollection.
  10999.  
  11000.     (view constructorView isNil)
  11001.         ifTrue: [view flash]
  11002.         ifFalse:
  11003.             [topView _ view topView.
  11004.              "remove my view"
  11005.              topView removeSubViews.
  11006.              "allow old controller to resume"
  11007.              view constructorView controller done: false.
  11008.              "reinstate old view and display it"
  11009.              topView addSubView: view constructorView.
  11010.              view constructorView scrollOffset: view scrollOffset.
  11011.              topView displaySubViews.
  11012.              self done: true.    "relinquish control"].!
  11013.  
  11014. compile
  11015.     "Compile my model into a module, making the currently selected parts external. The module is given a new name such as 'Module43'."
  11016.  
  11017.     | thingClass externalParts module constructorView topView |
  11018.     thingClass _ model thing class.
  11019.     externalParts _ 
  11020.         (model selected) collect:
  11021.             [: part | (part allTopParentPaths first) first].
  11022.     thingClass externalParts: externalParts asOrderedCollection.
  11023.     module _ ModuleCompiler compileThing: (model thing).
  11024.  
  11025.     "Return to the constructor view, but on the module"
  11026.     constructorView _ view constructorView.
  11027.     constructorView controller done: false.
  11028.     topView _ view topView.
  11029.     topView removeSubViews.
  11030.     topView addSubView: constructorView.
  11031.     constructorView controller viewThing: module.
  11032.     self done: true.    "relinquish control"! !
  11033.  
  11034. CodeController subclass: #ExplanationController
  11035.     instanceVariableNames: ''
  11036.     classVariableNames: ''
  11037.     poolDictionaries: ''
  11038.     category: 'ThingLabII-UI-Support'!
  11039. ExplanationController comment:
  11040. 'I am a controller for CodeViews on Explanations. I have a special implementation of accept that closes my top view.'!
  11041.  
  11042.  
  11043. !ExplanationController methodsFor: 'menu messages'!
  11044.  
  11045. accept
  11046.     "Accept the changes, if there are any, and close this explanation view."
  11047.  
  11048.     (self textHasChanged)
  11049.         ifTrue: [view accept: self text from: self].
  11050.     view topView controller close.!
  11051.  
  11052. menuActivity
  11053.  
  11054.     self yellowButtonActivity.! !
  11055.  
  11056. Model subclass: #Scene
  11057.     instanceVariableNames: 'glyphs selected '
  11058.     classVariableNames: ''
  11059.     poolDictionaries: ''
  11060.     category: 'ThingLabII-UI-Framework'!
  11061. Scene comment:
  11062. 'A Scene is a two-dimensional diagram or picture composed of displayable objects called glyphs. Each glyph must respond to the basic protocol for Glyphs (see class Glyph). A scene also maintains a list of selected glyphs and can enumerate various kinds of the glyphs: visible, selectable, and input-accepting.
  11063.  
  11064. Scenes maintain a list of selected glyphs.
  11065. '!
  11066.  
  11067.  
  11068. !Scene methodsFor: 'initialize-release'!
  11069.  
  11070. initialize
  11071.  
  11072.     glyphs _ OrderedCollection new.
  11073.     selected _ Set new.! !
  11074.  
  11075. !Scene methodsFor: 'glyphs access'!
  11076.  
  11077. allGlyphs
  11078.     "Answer the set of all glyphs. By default, this is just the visible glyphs."
  11079.  
  11080.     ^self visibleGlyphs!
  11081.  
  11082. inputGlyphs
  11083.     "Answer the set of glyphs that accept input."
  11084.  
  11085.     ^glyphs select: [: g | g wantsMouse | g wantsKeystrokes]!
  11086.  
  11087. selectableGlyphs
  11088.     "Answer the set of glyphs that are selectable. By default, this is just the visible glyphs."
  11089.  
  11090.     ^self visibleGlyphs!
  11091.  
  11092. visibleGlyphs
  11093.     "Answer the set of glyphs that are visible."
  11094.  
  11095.     ^glyphs! !
  11096.  
  11097. !Scene methodsFor: 'glyphs'!
  11098.  
  11099. addGlyph: aGlyph
  11100.  
  11101.     glyphs addLast: aGlyph!
  11102.  
  11103. isChanging: aGlyph
  11104.     "Answer true if the give glyph is undergoing changes that could effect how it is displayed. For example, this would be 'true' for glyphs being dragged with the mouse. By default, all glyphs are unchanging."
  11105.  
  11106.     ^selected includes: aGlyph!
  11107.  
  11108. moveToFront: glyphsList
  11109.     "Move the glyphs in the collection glyphsList to the back of my glyph collection so that they will be displayed last and hence appear in front of any overlapping glyphs."
  11110.  
  11111.     | temp |
  11112.     glyphsList do: [: g |
  11113.         temp _ glyphs remove: g ifAbsent: [nil].
  11114.         (temp notNil) ifTrue: [glyphs addLast: temp]].!
  11115.  
  11116. removeGlyph: aGlyph
  11117.  
  11118.     glyphs remove: aGlyph ifAbsent: [].
  11119.     selected remove: aGlyph ifAbsent: [].! !
  11120.  
  11121. !Scene methodsFor: 'selections'!
  11122.  
  11123. clearSelection
  11124.  
  11125.     selected _ selected species new.!
  11126.  
  11127. deselect: aGlyph
  11128.  
  11129.     selected remove: aGlyph ifAbsent: [].!
  11130.  
  11131. select: aGlyph
  11132.  
  11133.     selected add: aGlyph.!
  11134.  
  11135. selected
  11136.  
  11137.     ^selected!
  11138.  
  11139. toggleSelect: aGlyph
  11140.     "Toggle the selection of aGlyph. That is, if aGlyph is currently selected, deselect it; if it is not selected, select it."
  11141.  
  11142.     (selected includes: aGlyph)
  11143.         ifTrue: [self deselect: aGlyph]
  11144.         ifFalse: [self select: aGlyph]! !
  11145. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  11146.  
  11147. Scene class
  11148.     instanceVariableNames: ''!
  11149.  
  11150.  
  11151. !Scene class methodsFor: 'instance creation'!
  11152.  
  11153. new
  11154.  
  11155.     ^self basicNew initialize! !
  11156.  
  11157. Controller subclass: #IntroPicture
  11158.     instanceVariableNames: ''
  11159.     classVariableNames: ''
  11160.     poolDictionaries: ''
  11161.     category: 'ThingLabII-UI-Support'!
  11162. IntroPicture comment:
  11163. 'I support startup pictures. The picture will also appear after you snapshot. The startup picture is typically stored in a file such as ''ThingLabII.form''. I go away when the user presses any mouse button.'!
  11164.  
  11165.  
  11166. !IntroPicture methodsFor: 'control defaults'!
  11167.  
  11168. isControlActive
  11169.     "Hack, hack!! Seize control and don't give it up until the user clicks any mouse button."
  11170.  
  11171.     sensor waitClickButton.
  11172.     view topView controller close.
  11173.     ^false! !
  11174. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  11175.  
  11176. IntroPicture class
  11177.     instanceVariableNames: ''!
  11178.  
  11179.  
  11180. !IntroPicture class methodsFor: 'instance creation'!
  11181.  
  11182. openOn: aForm 
  11183.     "Display the ThingLabII intro picture."
  11184.     "IntroPicture openOn: (Form readFrom: 'ThingLabII.form')"
  11185.  
  11186.     | formView topView extent scratchForm |
  11187.     extent _ 354@332.
  11188.     Display boundingBox height - 30 < extent y
  11189.         ifTrue: [extent _ 318@294].
  11190.     scratchForm _ Form extent: extent.
  11191.     aForm
  11192.         displayOn: scratchForm
  11193.         at: ((extent - aForm boundingBox extent) // 2).
  11194.     formView _ FormView new model: scratchForm.
  11195.     formView controller: self new.
  11196.  
  11197.     topView _
  11198.         SpecialSystemView
  11199.             model: nil
  11200.             label: ' Welcome to ThingLabII '
  11201.             minimumSize: extent.
  11202.     topView addSubView: formView.
  11203.     topView window: (0@0 extent: extent)
  11204.         viewport: (0@0 extent: extent).
  11205.     topView controller openDisplayAt:
  11206.         (Display boundingBox center + (0@8)).! !
  11207.  
  11208. StandardSystemView subclass: #SpecialSystemView
  11209.     instanceVariableNames: ''
  11210.     classVariableNames: ''
  11211.     poolDictionaries: ''
  11212.     category: 'ThingLabII-UI-Support'!
  11213.  
  11214.  
  11215. !SpecialSystemView methodsFor: 'controller access'!
  11216.  
  11217. defaultControllerClass
  11218.  
  11219.     ^SpecialSystemController! !
  11220.  
  11221. !SpecialSystemView methodsFor: 'queries'!
  11222.  
  11223. isVisible
  11224.  
  11225.     ^(controller notNil) and: [controller isVisible]! !
  11226.  
  11227. !SpecialSystemView methodsFor: 'custom labels'!
  11228.  
  11229. displayLabel
  11230.     "Customized label display for that special look-n-feel."
  11231.  
  11232.     self isCollapsed ifTrue: [^self].
  11233.     isLabelComplemented _ false.
  11234.     "draw my label"
  11235.     (self labelForm)
  11236.         displayOn: Display
  11237.         at: self labelDisplayBox topLeft
  11238.         clippingBox: self labelDisplayBox.!
  11239.  
  11240. displayView
  11241.     "Display my label."
  11242.  
  11243.     self displayLabel!
  11244.  
  11245. expandLabelFrame
  11246.     "Make my label frame fill the entire width of my display box. Assume that labelFrame topLeft has already been computed."
  11247.  
  11248.     labelFrame
  11249.         right: self displayBox width;
  11250.         bottom:
  11251.             ((labelText notNil)
  11252.                 ifTrue: [labelText boundingBox height]
  11253.                 ifFalse: [TextStyle default lineGrid]).!
  11254.  
  11255. label: aString 
  11256.     "Set aString to be my label. There are two label sizes: one for real computers and the other for small Macintoshes (toy computers)."
  11257.  
  11258.     self label: aString big: (ThingLabIIControlPanel bigLabelFlag).
  11259.     self expandLabelFrame.!
  11260.  
  11261. label: aString big: bigFlag
  11262.     "Set aString to be my label. Use big text if bigFlag is true, otherwise use small text."
  11263.  
  11264.     | style |
  11265.     (aString == nil)
  11266.         ifTrue: 
  11267.             [labelText _ nil.
  11268.              labelFrame region: (0@0 extent: 0@0)]
  11269.         ifFalse:
  11270.             [bigFlag
  11271.                 ifTrue:
  11272.                     [style _ TextStyle fontArray: (Array with:
  11273.                         ((TextStyle styleNamed: #default) fontAt: 1)).
  11274.                      style baseline: 11; lineGrid: 17]
  11275.                 ifFalse:
  11276.                     [style _ TextStyle fontArray: (Array with:
  11277.                         ((TextStyle styleNamed: #small) fontAt: 1)).
  11278.                       style baseline: 9; lineGrid: 13].
  11279.              labelText _ Paragraph withText: aString asText style: style.
  11280.              labelFrame region:
  11281.                 (0@0 extent: labelText boundingBox extent)].
  11282.  
  11283.     (iconView notNil & iconText isNil)
  11284.         ifTrue: [iconView text: self label asText].!
  11285.  
  11286. labelForm
  11287.     "A customized label display for that special look-n-feel."
  11288.  
  11289.     | form textBox textPlace leftEdge rightEdge |
  11290.     form _ Form extent: labelFrame extent.
  11291.  
  11292.     "draw the label text"
  11293.     textBox _ self labelTextBox.
  11294.     textPlace _ form boundingBox center -
  11295.                 (textBox center - textBox topLeft).
  11296.     (labelText notNil) ifTrue:
  11297.         [labelText
  11298.             displayOn: form
  11299.             at: textPlace + (4@1)
  11300.             clippingBox: textBox].
  11301.  
  11302.     "draw decorative fringes"
  11303.     leftEdge _ textPlace x - 12.
  11304.     rightEdge _ textPlace x + textBox width.
  11305.  
  11306.     "left side fringe"
  11307.     form fill: (0@0 corner: leftEdge@form height) mask: Form lightGray.
  11308.     form fill: ((leftEdge@0) extent: 12@form height) mask: Form white.
  11309.     form fill: ((leftEdge@0) extent: 4@form height) mask: Form black.
  11310.     form fill: ((leftEdge + 6@0) extent: 2@form height) mask: Form black.
  11311.     form fill: ((leftEdge + 11@0) extent: 1@form height) mask: Form black.
  11312.  
  11313.     "right side fringe"
  11314.     form fill: (rightEdge@0 corner: form extent) mask: Form lightGray.
  11315.     form fill: ((rightEdge@0) extent: 12@form height) mask: Form white.
  11316.     form fill: ((rightEdge@0) extent: 1@form height) mask: Form black.
  11317.     form fill: ((rightEdge + 4@0) extent: 2@form height) mask: Form black.
  11318.     form fill: ((rightEdge + 8@0) extent: 4@form height) mask: Form black.
  11319.  
  11320.     "draw the border over everything else"
  11321.     form
  11322.         border: form boundingBox
  11323.         widthRectangle: ((1@1) corner: (1@0)) mask: (Form black).
  11324.     ^form!
  11325.  
  11326. labelTextBox
  11327.     "Answer the rectangle containing just the text part of my label. This rectangle is in the coordinate system whose origin is the top-left corner of my label."
  11328.  
  11329.     | textWidth |
  11330.     (labelText isNil)
  11331.         ifTrue: [textWidth _ 8]
  11332.         ifFalse: [textWidth _ labelText boundingBox width + 8].
  11333.     ^(0@1 corner: labelFrame extent) insetBy:
  11334.         ((1 max: ((labelFrame width - textWidth) // 2)) @ 0)!
  11335.  
  11336. labelTextDisplayBox.
  11337.     "Answer the rectangle containing just the text part of my label in the Display coordinate system."
  11338.  
  11339.     ^self labelTextBox translateBy: self labelDisplayBox origin!
  11340.  
  11341. reverseLabel
  11342.     "Reverse my label."
  11343.  
  11344.     Display reverse: (self labelTextDisplayBox).!
  11345.  
  11346. window: newWind viewport: newViewport
  11347.     "Intercept this message to allow me to re-compute my label frame when the view is re-sized."
  11348.  
  11349.     super window: newWind viewport: newViewport.
  11350.     self expandLabelFrame.! !
  11351.  
  11352. Object subclass: #ModuleCompiler
  11353.     instanceVariableNames: 'oldThing workThing newThing partitions internalVarCount '
  11354.     classVariableNames: ''
  11355.     poolDictionaries: ''
  11356.     category: 'ThingLabII-Module Compiler'!
  11357. ModuleCompiler comment:
  11358. 'This is is the top-level of the Module compiler that converts a Thing and a list of external parts into a ModuleThing and a set of ModuleConstraints.'!
  11359.  
  11360.  
  11361. !ModuleCompiler methodsFor: 'compiling'!
  11362.  
  11363. compileThing: aThing
  11364.     "This is the entry point of the ModuleCompiler. The module compiler manipulates a working copy of the original Thing to construct the new Module."
  11365.  
  11366.     | showOffView |
  11367.     oldThing _ aThing.
  11368.     workThing _ aThing clone.
  11369.     showOffView _ ModuleCompilerView open.    BusyCursor begin.
  11370.     self createPartitions.                        BusyCursor inc.
  11371.     self removeExternalPartConstraints.        BusyCursor inc.
  11372.     showOffView incrementState.                BusyCursor inc.
  11373.     self declareExternalVariables.                BusyCursor inc.
  11374.     self removePrivateAndEmptyPartitions.        BusyCursor inc.
  11375.     showOffView incrementState.                BusyCursor inc.
  11376.     partitions do:
  11377.         [: partition |
  11378.          partition computeSolutions.            BusyCursor inc.
  11379.          partition analyzeSolutions.            BusyCursor inc].
  11380.     showOffView incrementState.                BusyCursor inc.
  11381.     self numberPartitions.                BusyCursor inc.
  11382.     self allocateInternalVariables.                BusyCursor inc.
  11383.     showOffView incrementState.                BusyCursor inc.
  11384.     self constructNewClass.                    BusyCursor inc.
  11385.     self initializePrototype.                    BusyCursor inc.
  11386.     showOffView incrementState.                BusyCursor inc.
  11387.     self buildAndAddConstraints.                BusyCursor inc.
  11388.     workThing destroy.                        BusyCursor inc.
  11389.     showOffView closeAndRemove.                BusyCursor end.
  11390.     ^newThing! !
  11391.  
  11392. !ModuleCompiler methodsFor: 'private'!
  11393.  
  11394. addConstrainedPartPathsFor: aPart from: pathSoFar into: paths
  11395.     "Recursively collect full paths for all constrained subparts of aPart into the given collection of paths. The path to this point is pathSoFar."
  11396.  
  11397.     (aPart isThing) ifTrue:
  11398.         [aPart partsAndNamesDo:
  11399.             [: part : partName |
  11400.              ((aPart thingDataFor: partName) notNil) ifTrue:
  11401.                 [paths add: (pathSoFar copyWith: partName asSymbol)].
  11402.              self
  11403.                 addConstrainedPartPathsFor: part
  11404.                 from: (pathSoFar copyWith: partName asSymbol)
  11405.                 into: paths]].!
  11406.  
  11407. allocateInternalVariables
  11408.     "Allocate internal variable names to the partitions. Internal variables are given names like 'internal1'."
  11409.  
  11410.     internalVarCount _ 0.
  11411.     partitions do:
  11412.         [: partition |
  11413.          internalVarCount _
  11414.             partition allocateInternalVariables: internalVarCount].!
  11415.  
  11416. buildAndAddConstraints
  11417.     "Construct module constraints for all partitions and add them to newThing."
  11418.  
  11419.     | constraint |
  11420.     partitions do:
  11421.         [: p |
  11422.          constraint _ p compileFor: newThing.
  11423.          "allocate thingDatas before adding the constraint; the module methods assume they are there"
  11424.          constraint variables do: [: v | v thingDataOrAllocate].
  11425.          newThing addConstraint: constraint].!
  11426.  
  11427. constructNewClass
  11428.     "Build a new class for the module. This class will be a subclass of ModuleThing and will have instance variables for the external parts and the internal variables. Access methods must be compiled for the external parts."
  11429.  
  11430.     | instVarStream moduleName newClass externalThings |
  11431.     "build a list of instance variables for the new Module's class"
  11432.     instVarStream _ WriteStream on: String new.
  11433.     1 to: internalVarCount do:
  11434.         [: n | instVarStream nextPutAll: 'internal', n printString; space].
  11435.     oldThing class externalParts do: 
  11436.         [: var | instVarStream nextPutAll: var; space].
  11437.  
  11438.     "build the new Module's class"
  11439.     moduleName _ 'Module', ThingLabII uniqueNumber printString.
  11440.     newClass _ ModuleThing
  11441.         subclass: moduleName asSymbol
  11442.         instanceVariableNames: instVarStream contents
  11443.         classVariableNames: ''
  11444.         poolDictionaries: ''
  11445.         category: 'Things-Built'.
  11446.  
  11447.     "initialize the modules' class instance variables"
  11448.     newClass
  11449.         initializeForSourceClass: oldThing class
  11450.         internalPartCount: internalVarCount.
  11451.     newThing _ newClass prototype.
  11452.  
  11453.     "set up use/construction links"
  11454.     oldThing class useView: newClass.
  11455.     newThing class constructionView: oldThing class.
  11456.  
  11457.     "build custom access methods for the external parts"
  11458.     externalThings _ oldThing class externalParts collect:
  11459.         [: name | oldThing perform: name asSymbol].
  11460.     newThing class
  11461.         compileAccessMethodsFor: externalThings
  11462.         named: (oldThing class externalParts).
  11463.  
  11464.     "compile the instance offset class method for the new class"
  11465.     newClass compileInstOffsetMethodAs: ModuleThing instOffset + internalVarCount.!
  11466.  
  11467. createPartitions
  11468.     "Partition the constraints of workThing, creating a ModulePartition for each connected set of constraints."
  11469.  
  11470.     partitions _ (Partitioner partition: workThing) collect:
  11471.         [: partitionConstraints |
  11472.          ModulePartition on: partitionConstraints].!
  11473.  
  11474. declareExternalVariables
  11475.     "Construct a set of references for the constrained subparts of the external parts of workThing. The references must contain paths starting with external part names. Use this set of references to declare the external variables for each partition."
  11476.  
  11477.     | paths part externalRefs |
  11478.     paths _ OrderedCollection new: 40.
  11479.     (workThing class externalParts) do:
  11480.         [: partName |
  11481.          ((workThing thingDataFor: partName) notNil) ifTrue:
  11482.             [paths add: (Array with: partName)].
  11483.          part _ workThing perform: partName.
  11484.          self
  11485.             addConstrainedPartPathsFor: part
  11486.             from: (Array with: partName)
  11487.             into: paths].
  11488.     externalRefs _ paths collect:
  11489.         [: path | Reference on: workThing path: path].
  11490.  
  11491.     "identify the external variables in each partition"
  11492.     partitions do:
  11493.         [: partition |
  11494.          partition declareExternalVars: externalRefs].!
  11495.  
  11496. initializePrototype
  11497.     "Initialize the external parts of the prototype with clones of the corresponding parts from workThing. Also initialize the internal variables."
  11498.  
  11499.     | tempThing extParts partRef allThingDatas cloneDictionary clone partName index |
  11500.     tempThing _ oldThing clone.
  11501.     "first, make sure external parts are not entangled with any doomed internal parts. this is done by isolating the non-external parts from merges and removing their constraints. we must also remove the top-level constraints from tempThing."
  11502.     extParts _ (tempThing class externalParts) asSet.
  11503.     tempThing thingPartsAndNamesDo:
  11504.         [: part : name |
  11505.          (extParts includes: name) ifFalse:
  11506.             ["isolate the part"
  11507.              partRef _ part referenceToYourself.
  11508.              part isolate: partRef within: partRef.
  11509.              "remove all constraints attached to the part"
  11510.              allThingDatas _ Set new.
  11511.              part allThingDatasInto: allThingDatas.
  11512.              allThingDatas do: 
  11513.                 [: thingData | 
  11514.                  BusyCursor inc.
  11515.                  thingData constraints do: [: c | c removeConstraint]]]].
  11516.  
  11517.     tempThing constraints copy do: [: c | c destroy].
  11518.     tempThing constraints: tempThing constraints species new.
  11519.  
  11520.     "now, copy the external parts to the new module prototype. this is done using the cloning operation but moving the parts and changing the clone dictionary midway through."
  11521.     cloneDictionary _ IdentityDictionary new: 200.
  11522.     clone _ tempThing clonePass1: cloneDictionary.
  11523.     "move the newly copied external parts to their new home"
  11524.     newThing class partNamesAndIndices do:
  11525.         [: partAndIndex |
  11526.          partName _ partAndIndex at: 1.
  11527.          index _ partAndIndex at: 2.
  11528.          part _ clone perform: partName.
  11529.          newThing instVarAt: index put: part.
  11530.          part removeParent: clone.
  11531.          part addParent: newThing].
  11532.     "fix all references by changing old references to tempThing to go to newThing, using pass2 of the cloning operation."
  11533.     cloneDictionary at: tempThing put: newThing.
  11534.     clone clonePass2: cloneDictionary.
  11535.  
  11536.     partitions do: [: p | p initializeInternalVarsFor: newThing].
  11537.     tempThing destroy.!
  11538.  
  11539. numberPartitions
  11540.     "Assign a unique number to each partition."
  11541.  
  11542.     | nextId |
  11543.     nextId _ 0.
  11544.     partitions do:
  11545.         [: partition |
  11546.          partition setID: (nextId _ nextId + 1)].!
  11547.  
  11548. removeExternalPartConstraints
  11549.     "Remove constraints owned by the external parts from all partitions."
  11550.  
  11551.     | externalConstraints part |
  11552.     "first, collect the constraints owned by external parts"
  11553.     externalConstraints _ IdentitySet new: 20.
  11554.     workThing class externalParts do:
  11555.         [: partName |
  11556.          part _ workThing perform: partName.
  11557.          (part isThing) ifTrue:
  11558.             [part allThingsDo:
  11559.                 [: thing | externalConstraints addAll: thing constraints]]].
  11560.  
  11561.     "remove the external constraints from all partitions"
  11562.     partitions do:
  11563.         [: partition |
  11564.          partition removeExternalPartConstraints: externalConstraints].
  11565.  
  11566.     "release the external constraints"
  11567.     externalConstraints do: [: c | c removeConstraint; destroy].!
  11568.  
  11569. removePrivateAndEmptyPartitions
  11570.     "Filter out partitions with no external variables since these partitions cannot be seen from outside the module. Filter out partitions which have no constraints because they required no further processing."
  11571.  
  11572.     partitions _ partitions select:
  11573.         [: p | (p hasExternalVars) and: [p isEmpty not]].! !
  11574. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  11575.  
  11576. ModuleCompiler class
  11577.     instanceVariableNames: ''!
  11578.  
  11579.  
  11580. !ModuleCompiler class methodsFor: 'compiling'!
  11581.  
  11582. compileThing: aThing
  11583.     "Create a new instance of me and use it to compile the given thing into a Module."
  11584.  
  11585.     ^self new compileThing: aThing! !
  11586.  
  11587. Constraint subclass: #EditConstraint
  11588.     instanceVariableNames: ''
  11589.     classVariableNames: 'SharedMethods '
  11590.     poolDictionaries: ''
  11591.     category: 'ThingLabII-Constraints-Special'!
  11592. EditConstraint comment:
  11593. 'I am used to mark variable that the user wishes to edit. I have only one method with no inputs and one output. My method does nothing.'!
  11594.  
  11595.  
  11596. !EditConstraint methodsFor: 'initialize-release'!
  11597.  
  11598. ref: ref strength: aSymbol 
  11599.     "Initialize myself with the given reference and strength."
  11600.  
  11601.     strength _ Strength of: aSymbol.
  11602.     symbols _ #(a).
  11603.     self variables: (Array with: ref).
  11604.     "initialize methods list shared by all instances"
  11605.     (SharedMethods isNil) ifTrue:
  11606.         [SharedMethods _ Array with:
  11607.             ((Method new)
  11608.                 codeString: '"edit"';
  11609.                 block: [: vars | "I do nothing" vars _ nil];
  11610.                 bindings: 'o')].
  11611.     self methods: SharedMethods.
  11612.     whichMethod _ nil.
  11613.     self initializeFlags.! !
  11614.  
  11615. !EditConstraint methodsFor: 'queries'!
  11616.  
  11617. doesSomething
  11618.     "Edit constraints have no effect other than to control the planning process."
  11619.  
  11620.     ^false!
  11621.  
  11622. isInput
  11623.     "Normal constraints are not input constraints. An input constraint is one that depends on external state, such as the mouse, the keyboard, or a clock."
  11624.  
  11625.     ^true! !
  11626. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  11627.  
  11628. EditConstraint class
  11629.     instanceVariableNames: ''!
  11630.  
  11631.  
  11632. !EditConstraint class methodsFor: 'instance creation'!
  11633.  
  11634. ref: ref
  11635.     "Answer a new instance of me on the referenced variable with the current edit strength."
  11636.  
  11637.     ^self ref: ref strength: ThingLabII editStrength!
  11638.  
  11639. ref: ref strength: strength
  11640.     "Create a new edit constraint on the referenced variable. For example:
  11641.  
  11642.     EditConstraint
  11643.         ref: aThing->#node.value
  11644.         strength: #preferred."
  11645.  
  11646.     ^(super new) ref: ref strength: strength! !
  11647.  
  11648. Scene subclass: #ThingDebug
  11649.     instanceVariableNames: 'thing variables partitions currentPartition solvers solutionIndex '
  11650.     classVariableNames: ''
  11651.     poolDictionaries: ''
  11652.     category: 'ThingLabII-UI-Debugger'!
  11653.  
  11654.  
  11655. !ThingDebug methodsFor: 'initialize-release'!
  11656.  
  11657. buildButtons
  11658.     "Construct buttons for navigating through the partitions and solutions."
  11659.  
  11660.     | leftArrowForm rightArrowForm |
  11661.     leftArrowForm _ (Form
  11662.         extent: 10@9
  11663.         fromArray: #(3072 7168 15360 32704 65472 32704 15360 7168 3072)
  11664.         offset: 0@0).
  11665.     rightArrowForm _ leftArrowForm rotateBy: 2.
  11666.     self addGlyph: ((ButtonGlyph at: 21@20 form: leftArrowForm)
  11667.                      action: [: v | self previousPartition]).
  11668.     self addGlyph: ((ButtonGlyph at: 38@20 form: rightArrowForm)
  11669.                      action: [: v | self nextPartition]).
  11670.     self addGlyph: ((ButtonGlyph at: 21@34 form: leftArrowForm)
  11671.                      action: [: v | self previousAlternative]).
  11672.     self addGlyph: ((ButtonGlyph at: 38@34 form: rightArrowForm)
  11673.                      action: [: v | self nextAlternative]).!
  11674.  
  11675. buildPartitions
  11676.     "Build ThingDebug of data structures for the partitions of my Thing."
  11677.  
  11678.     | partitionRecord constraintRecord |
  11679.     partitions _ (Partitioner partition: thing) collect:
  11680.         [: partition |
  11681.          partitionRecord _ DebugPartitionRecord new.
  11682.          partitionRecord
  11683.             solver: (MultiSolver on: partition);
  11684.              constraintRecords: (partition collect:
  11685.                 [: constraint |
  11686.                  constraintRecord _ DebugConstraintRecord new.
  11687.                  constraintRecord
  11688.                     constraint: constraint;
  11689.                      glyph: (ConstraintGlyph named: (self strengthString: constraint));
  11690.                     solutions: (OrderedCollection with: constraint whichMethod)]).
  11691.          partitionRecord].!
  11692.  
  11693. buildVariableTable
  11694.     "Build a dictionary of all constrained variables. The dictionary maps ThingDatas to VariableGlyphs. The information is extracted from the partitions, which must already have been built."
  11695.  
  11696.     | constraint glyph |
  11697.     variables _ IdentityDictionary new.
  11698.     partitions do:
  11699.         [: partition |
  11700.          partition constraintRecords do:
  11701.             [: cRec |
  11702.              cRec constraint variables do:
  11703.                 [: v |
  11704.                  (variables includesKey: v thingData) ifFalse:
  11705.                      [glyph _ VariableGlyph
  11706.                                 named: (v longName)
  11707.                                 at:  (self nextPlace).
  11708.                      variables at: v thingData put: glyph]].
  11709.              cRec varGlyphs:
  11710.                 (cRec constraint variables collect:
  11711.                     [: v | variables at: v thingData])]].!
  11712.  
  11713. on: aThing
  11714.     "Initialize a new instance of me on the given Thing and build the partitions and variables table."
  11715.  
  11716.     super initialize.
  11717.     thing _ aThing.
  11718.     currentPartition _ 1.
  11719.     self buildButtons.
  11720.     self buildPartitions.
  11721.     self buildVariableTable.
  11722.     partitions do:
  11723.         [: partition |
  11724.          partition solution: 0.
  11725.          partition centerConstraints].
  11726.     self firstPartition.! !
  11727.  
  11728. !ThingDebug methodsFor: 'glyphs'!
  11729.  
  11730. isChanging: aGlyph
  11731.     "Answer true if the following glyph is changing. This is the case if the glyph is selected or if it is a ConstraintGlyph and one of its associated variables is selected."
  11732.  
  11733.     (selected includes: aGlyph) ifTrue: [^true].
  11734.     (aGlyph isMemberOf: ConstraintGlyph) ifTrue:
  11735.         [aGlyph allVarGlyphs do:
  11736.             [: var |
  11737.              (selected includes: var) ifTrue: [^true]]].
  11738.     ^false!
  11739.  
  11740. selectableGlyphs
  11741.  
  11742.     ^glyphs select: [: g | (g isMemberOf: ButtonGlyph) not]! !
  11743.  
  11744. !ThingDebug methodsFor: 'partitions'!
  11745.  
  11746. firstPartition
  11747.     "Display the first partition."
  11748.  
  11749.     currentPartition _ 1.
  11750.     self updateGlyphs.!
  11751.  
  11752. nextPartition
  11753.     "Display the next partition. Wrap around at the end of the list of partitions."
  11754.  
  11755.     currentPartition _ (currentPartition \\ partitions size) + 1.
  11756.     self updateGlyphs.!
  11757.  
  11758. partitionCount
  11759.     "Answer the total number of constraint partitions for my Thing."
  11760.  
  11761.     ^partitions size!
  11762.  
  11763. partitionIndex
  11764.     "Answer the index of the current partition."
  11765.  
  11766.     ^currentPartition!
  11767.  
  11768. previousPartition
  11769.     "Display the previous partition. Wrap around at the beginning of the list of partitions."
  11770.  
  11771.     currentPartition _ ((currentPartition - 2) \\ partitions size) + 1.
  11772.     self updateGlyphs.! !
  11773.  
  11774. !ThingDebug methodsFor: 'solutions'!
  11775.  
  11776. currentSolution
  11777.     "Display solution zero, the current solution, for the current partition."
  11778.  
  11779.     (partitions at: currentPartition) solution: 0.!
  11780.  
  11781. nextAlternative
  11782.     "Display the next alternative solution for this partition. Wrap around at the end of the solutions list. If the alternative solutions have not yet been computed for this partition, compute them now."
  11783.  
  11784.     | partition |
  11785.     (self solutionCount = 0) ifTrue:
  11786.         [Cursor execute showWhile: [self computeAllSolutions]].
  11787.     partition _ partitions at: currentPartition.
  11788.     partition solution:
  11789.         ((partition solution + 1) \\ (partition solutionCount + 1)).!
  11790.  
  11791. previousAlternative
  11792.     "Display the next previous solution for this partition. Wrap around at the beginning of the solutions list. If the alternative solutions have not yet been computed for this partition, compute them now."
  11793.  
  11794.     | partition |
  11795.     (self solutionCount = 0) ifTrue:
  11796.         [Cursor execute showWhile: [self computeAllSolutions]].
  11797.     partition _ partitions at: currentPartition.
  11798.     partition solution:
  11799.         ((partition solution - 1) \\ (partition solutionCount + 1)).!
  11800.  
  11801. solutionCount
  11802.     "Answer the number of possible solutions for this partition."
  11803.  
  11804.     ^(partitions at: currentPartition) solutionCount!
  11805.  
  11806. solutionHasCycle
  11807.     "Answer true if the current solution has a cycle."
  11808.  
  11809.     ^(partitions at: currentPartition) solutionHasCycle!
  11810.  
  11811. solutionIndex
  11812.     "Answer the index of the displayed solution for the current partition. Zero means the current solution."
  11813.  
  11814.     ^(partitions at: currentPartition) solution! !
  11815.  
  11816. !ThingDebug methodsFor: 'operations'!
  11817.  
  11818. animateOn: aView
  11819.     "Animate the layout algorithm."
  11820.  
  11821.     (partitions at: currentPartition) animateOn: aView.!
  11822.  
  11823. centerConstraints
  11824.     "Center all constraints between their operands."
  11825.  
  11826.     (partitions at: currentPartition) centerConstraints.!
  11827.  
  11828. rebuildFromThing
  11829.     "Completely rebuild my data structures from my Thing. This is useful when the structure of the underlying Thing has been changed but the user wants to keep using the same ThingDebugView."
  11830.  
  11831.     self on: thing.!
  11832.  
  11833. toggleConstraintLabels
  11834.     "Toggle the visibility of the constraint labels of the current partition."
  11835.  
  11836.     (partitions at: currentPartition) toggleLabels.!
  11837.  
  11838. toggleVariableLabels
  11839.     "Toggle the visibility of all variable labels."
  11840.  
  11841.     (variables asOrderedCollection first labelIsHidden)
  11842.         ifTrue: [variables do: [: v | v showLabel]]
  11843.         ifFalse: [variables do: [: v | v hideLabel]].!
  11844.  
  11845. updateCurrentSolutions
  11846.     "Update the current solution of each partition."
  11847.  
  11848.     partitions do:
  11849.         [: partition |
  11850.          partition updateCurrentSolution].! !
  11851.  
  11852. !ThingDebug methodsFor: 'private'!
  11853.  
  11854. computeAllSolutions
  11855.     "This can be very expensive for large partitions!! Find and record all the possible solutions for this partition so that the user may browse through them."
  11856.  
  11857.     (partitions at: currentPartition) findAllSolutions.!
  11858.  
  11859. nextPlace
  11860.  
  11861.     |  random x y |
  11862.     random _ Random new.
  11863.     x _ (random next * 200) rounded.
  11864.     y _ (random next * 200) rounded.
  11865.     ^(60@40) + (x@y)!
  11866.  
  11867. strengthString: aConstraint
  11868.     "Answer an abbreviation of the constraint's strength."
  11869.  
  11870.     | sym |
  11871.     sym _ aConstraint strength asSymbol.
  11872.     (sym == #required) ifTrue: [^'R'].
  11873.     (sym == #strongPreferred) ifTrue: [^'sP'].
  11874.     (sym == #preferred) ifTrue: [^'P'].
  11875.     (sym == #strongDefault) ifTrue: [^'sD'].
  11876.     (sym == #default) ifTrue: [^'D'].
  11877.     (sym == #weakDefault) ifTrue: [^'wD'].
  11878.     ^'(', sym, ')'!
  11879.  
  11880. updateGlyphs
  11881.     "Update my glyphs after changing partitions."
  11882.  
  11883.     | partition varGlyphs |
  11884.     (partitions isEmpty) ifTrue: [^self].
  11885.     partition _ partitions at: currentPartition.
  11886.  
  11887.     glyphs _ glyphs select:
  11888.         [: g | ((g isMemberOf: VariableGlyph) | (g isMemberOf: ConstraintGlyph)) not].
  11889.     self clearSelection.
  11890.  
  11891.     varGlyphs _ IdentitySet new: 20.
  11892.     partition constraintRecords do:
  11893.         [: cRec |
  11894.          glyphs add: cRec glyph.
  11895.          varGlyphs addAll: cRec varGlyphs].
  11896.     glyphs addAll: varGlyphs.
  11897.  
  11898.     (partition neverLaidOut) ifTrue: [partition initialLayout].! !
  11899. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  11900.  
  11901. ThingDebug class
  11902.     instanceVariableNames: ''!
  11903.  
  11904.  
  11905. !ThingDebug class methodsFor: 'instance creation'!
  11906.  
  11907. on: aThing
  11908.     "Create a new instance on the given Thing."
  11909.  
  11910.     ^(super new) on: aThing! !
  11911.  
  11912. Constraint subclass: #StayConstraint
  11913.     instanceVariableNames: ''
  11914.     classVariableNames: 'SharedMethods '
  11915.     poolDictionaries: ''
  11916.     category: 'ThingLabII-Constraints-Special'!
  11917. StayConstraint comment:
  11918. 'I am used to mark variables should, with some level of preference, stay the same. I have only one method with no inputs and one output. My method does nothing. Planners may use the fact that, if I am satisfied, my output will not change to perform stay optimization.'!
  11919.  
  11920.  
  11921. !StayConstraint methodsFor: 'initialize-release'!
  11922.  
  11923. ref: ref strength: aSymbol 
  11924.     "Initialize myself with the given reference and strength."
  11925.  
  11926.     strength _ Strength of: aSymbol.
  11927.     symbols _ #(a).
  11928.     self variables: (Array with: ref).
  11929.     "initialize methods list shared by all instances"
  11930.     (SharedMethods isNil) ifTrue:
  11931.         [SharedMethods _ Array with:
  11932.             ((Method new)
  11933.                 codeString: '"stay"';
  11934.                 block: [: vars | "I do nothing" vars _ nil];
  11935.                 bindings: 'o')].
  11936.     self methods: SharedMethods.
  11937.     whichMethod _ nil.
  11938.     self initializeFlags.! !
  11939.  
  11940. !StayConstraint methodsFor: 'queries'!
  11941.  
  11942. doesSomething
  11943.     "Stay constraints have no effect other than to control the planning process."
  11944.  
  11945.     ^false!
  11946.  
  11947. isStay
  11948.     "I am a stay constraint."
  11949.  
  11950.     ^true! !
  11951. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  11952.  
  11953. StayConstraint class
  11954.     instanceVariableNames: ''!
  11955.  
  11956.  
  11957. !StayConstraint class methodsFor: 'instance creation'!
  11958.  
  11959. ref: ref strength: strength
  11960.     "Create a new stay constraint on the referenced variable. For example:
  11961.  
  11962.     StayConstraint
  11963.         ref: aThing->#midpoint.y
  11964.         strength: #default."
  11965.  
  11966.     ^(super new) ref: ref strength: strength! !
  11967.  
  11968. Object subclass: #Glyph
  11969.     instanceVariableNames: 'location '
  11970.     classVariableNames: ''
  11971.     poolDictionaries: ''
  11972.     category: 'ThingLabII-UI-Framework'!
  11973. Glyph comment:
  11974. 'This is an abstract class that defines the protocol used by components of a Scene to permit them to be laid out, displayed, and selected. Subclasses must implement the methods specified as ''subclassResponsibility'' (which are currently only displayOn:at:clippingBox: and boundingBox, but don''t trust this comment!!).'!
  11975.  
  11976.  
  11977. !Glyph methodsFor: 'initialize-release'!
  11978.  
  11979. initialize
  11980.     "Initialize myself with default values. Subclasses should do 'super initialize' when overriding this method to ensure that instance variables owned by their superclass are properly initialized."
  11981.  
  11982.     location _ 0@0.! !
  11983.  
  11984. !Glyph methodsFor: 'accessing'!
  11985.  
  11986. location
  11987.  
  11988.     ^location!
  11989.  
  11990. location: aPoint
  11991.  
  11992.     location _ aPoint.! !
  11993.  
  11994. !Glyph methodsFor: 'glyph protocol'!
  11995.  
  11996. boundingBox
  11997.     "Answer a Rectangle that completely surrounds all visible parts of me."
  11998.  
  11999.     ^self subclassResponsibility!
  12000.  
  12001. containsPoint: aPoint
  12002.     "More complex subclasses may refine this method."
  12003.  
  12004.     ^self boundingBox containsPoint: aPoint!
  12005.  
  12006. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox 
  12007.     "Draw myself. The default is to do nothing. Visible glyphs supply a more specialized behavior for this method."!
  12008.  
  12009. glyphsComment
  12010.     "This protocol describes the basic operations on graphical objects known as 'glyphs'. A glyph may be displayed, selected, and moved. The three categories of glyphs are:
  12011.  
  12012.     1. visible glyphs -- glyphs that are visible in the display
  12013.     2. selectable glyphs -- glyphs that can be selected and moved
  12014.     3. input glyphs -- glyphs that respond to keyboard and/or mouse events
  12015.  
  12016. These categories are orthogonal, so it is possible to have visible glyphs that cannot be selected and moved or glyphs that can be selected but are not visible.
  12017.  
  12018. All glyphs must respond to basic glyph protocol:
  12019.     boundingBox -- Essential!!
  12020.     displayOn:at:clippingBox:
  12021.     boundingBox
  12022.     initialize
  12023. The only essential message is boundingBox; default behavior is provided for the other messages, although since the default displayOn:at:clippingBox: behavior is to do nothing, a glyph that does not override this default will be invisible.
  12024.  
  12025. For a glyph to be considered an input glyph, it must also answer true to one of:
  12026.     wantsKeystrokes
  12027.     wantsMouse
  12028. and it must support the corresponding keyboard and/or mouse prototcol."!
  12029.  
  12030. highlightOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox 
  12031.     "This is the default highlighted glyph display method, which merely draws a box around itself. Subclasses may refine this."
  12032.  
  12033.     aDisplayMedium
  12034.         border: ((self boundingBox translateBy: aDisplayPoint)
  12035.                     insetOriginBy: -2@-2 cornerBy: -2@-2)
  12036.         widthRectangle: (1@1 corner: 1@1)
  12037.         mask: (Form black)
  12038.         clippingBox: clipBox.!
  12039.  
  12040. intersects: aRectOrGlyph
  12041.     "Answer true if I interesect with the given object, which may be either a Rectangle or a Glyph."
  12042.  
  12043.     (aRectOrGlyph isMemberOf: Rectangle)
  12044.         ifTrue:
  12045.             [^aRectOrGlyph intersects: self boundingBox]
  12046.         ifFalse:
  12047.             [^aRectOrGlyph boundingBox intersects: self boundingBox].! !
  12048.  
  12049. !Glyph methodsFor: 'keyboard'!
  12050.  
  12051. handleKeystroke: aCharacter view: aView
  12052.     "Accept the given character. The default behavior is to do nothing."!
  12053.  
  12054. wantsKeystrokes
  12055.     "Answer true if I want to get keyboard input. The default behavior is to answer false."
  12056.  
  12057.     ^false! !
  12058.  
  12059. !Glyph methodsFor: 'mouse'!
  12060.  
  12061. handleMouseDown: mousePoint view: aView
  12062.     "The mouse button has been pressed. mousePoint is in local coordinates. The default behavior is to do nothing."!
  12063.  
  12064. handleMouseMove: mousePoint view: aView
  12065.     "The message is sent repeatedly while the mouse button is pressed. mousePoint is in local coordinates. The default behavior is to do nothing."!
  12066.  
  12067. handleMouseUp: mousePoint view: aView
  12068.     "The mouse button has gone up. mousePoint is in local coordinates. The default behavior is to do nothing."!
  12069.  
  12070. mouseComment
  12071.  
  12072.     "When mouse input is initiated, the following sequence of events occurs:
  12073.     1. handleMouseDown:view: is sent to the glyph (exactly once)
  12074.     2. handleMouseMove: is sent to the glyph repeatedly while the mouse is down (at least once)
  12075.     3. handleMouseUp: is sent to the glyph (exactly once)
  12076.  
  12077. All of these messages have two arguments: 1) the current mouse position in local coordinates and 2) the view in which this Glyph appears."!
  12078.  
  12079. wantsMouse
  12080.     "Answer true if I want to be informed of mouse activity. The default behavior is to answer false."
  12081.  
  12082.     ^false! !
  12083. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  12084.  
  12085. Glyph class
  12086.     instanceVariableNames: ''!
  12087.  
  12088.  
  12089. !Glyph class methodsFor: 'instance creation'!
  12090.  
  12091. new
  12092.     "Answer a new Glyph at 0@0."
  12093.  
  12094.     ^self basicNew initialize! !
  12095.  
  12096. ModuleDisjunction subclass: #ModuleConjunction
  12097.     instanceVariableNames: 'varEquations orEquations '
  12098.     classVariableNames: ''
  12099.     poolDictionaries: ''
  12100.     category: 'ThingLabII-Module Compiler'!
  12101. ModuleConjunction comment:
  12102. 'I represent a conjunction (AND) of terms.
  12103.  
  12104. Each term has one of the following forms:
  12105.     1. aStrength <= aWalkEquation
  12106.     2. aModuleVarTableEntry <= aWalkEquation
  12107.     3. an OrEquation
  12108.  
  12109. Terms of the first form are kept in an OrderedCollection of Arrays of the form:
  12110.     (aStrength, aWalkEquation)
  12111. while terms of the second form are kept in a dictionary indexed by variable. The entries of this dictionary are WalkEquations. Terms of the third form are kept in an OrderedCollection.
  12112.  
  12113. My simplification rules are similar to those of OrEquations, except that:
  12114.     1. ''true'' terms are removed instead of ''false'' terms
  12115.     2. a ''false'' term makes the entire conjection ''false'' regardless of other terms
  12116.     3. OrEquation terms are simplified
  12117.  
  12118. Instance variables (in addition to those inherited):
  12119.  
  12120.     varEquations...        maps ModuleVarTableEntries to WalkEquations
  12121.     orEquations...            a collection of OrEquations
  12122. '!
  12123.  
  12124.  
  12125. !ModuleConjunction methodsFor: 'initialize-release'!
  12126.  
  12127. initialize
  12128.  
  12129.     super initialize.
  12130.     varEquations _ IdentityDictionary new.
  12131.     orEquations _ OrderedCollection new.! !
  12132.  
  12133. !ModuleConjunction methodsFor: 'operations'!
  12134.  
  12135. addOrTerm: orEquation
  12136.     "Add the given disjunctive term. If it has only one term, remove the enclosing disjunction and add the term inside."
  12137.  
  12138.     (orEquation hasOnlyOneTerm)
  12139.         ifTrue: [orEquation addTermsTo: self]
  12140.         ifFalse: [orEquations add: orEquation].
  12141.     knownValue _ nil.!
  12142.  
  12143. var: var weakerOrEq: walkEquation
  12144.     "Add an equation of the form:
  12145.         var <= walkEquation
  12146.     walkEquation is a WalkEquation of the form 'A weakest: B weakest: C ...'
  12147.     var is a ModuleVarTableEntry"
  12148.  
  12149.     | newEq |
  12150.     (varEquations includesKey: var)
  12151.         ifTrue:
  12152.             [newEq _ (varEquations at: var) weakest: walkEquation.
  12153.              varEquations at: var put: newEq]
  12154.         ifFalse:
  12155.             [varEquations at: var put: walkEquation].
  12156.     knownValue _ nil.! !
  12157.  
  12158. !ModuleConjunction methodsFor: 'printing'!
  12159.  
  12160. printOn: aStream
  12161.  
  12162.     | left right |
  12163.     aStream nextPutAll: 'AND('; cr.
  12164.     constEquations do:
  12165.         [: eqn | self printLeft: (eqn at: 1) right: (eqn at: 2) on: aStream].
  12166.     varEquations associationsDo:
  12167.         [: eqn | self printLeft: (eqn key) right: (eqn value) on: aStream].
  12168.     orEquations do:
  12169.         [: eqn | eqn printOn: aStream].
  12170.     aStream nextPutAll: ')'; cr.! !
  12171.  
  12172. !ModuleConjunction methodsFor: 'code generation'!
  12173.  
  12174. storeOn: aStream
  12175.     "Append to aStream code to be compiled to evalute myself at run-time."
  12176.  
  12177.     (self isTrue) ifTrue: [^aStream nextPutAll: 'true'].
  12178.     (self isFalse) ifTrue: [^aStream nextPutAll: 'false'].
  12179.     constEquations do:
  12180.         [: eqn |
  12181.          aStream tab.
  12182.          self codeLeft: (eqn at: 1) right: (eqn at: 2) on: aStream.
  12183.          aStream nextPutAll: ' &'; cr].
  12184.     varEquations associationsDo:
  12185.         [: eqn |
  12186.          aStream tab.
  12187.          self codeLeft: (eqn key) right: (eqn value) on: aStream.
  12188.          aStream nextPutAll: ' &'; cr].
  12189.     orEquations do:
  12190.         [: eqn |
  12191.          aStream tab.
  12192.          eqn storeOn: aStream.
  12193.          aStream nextPutAll: ' &'; cr].
  12194.     (constEquations isEmpty & varEquations isEmpty & orEquations isEmpty) ifFalse:
  12195.         [aStream skip: -3].! !
  12196.  
  12197. !ModuleConjunction methodsFor: 'private'!
  12198.  
  12199. emptyCheck
  12200.     "See if I have no terms and, if so, set my knownValue based on this."
  12201.     "An empty conjunction (AND) is true because the true constant terms were filtered out."
  12202.  
  12203.     (constEquations isEmpty & varEquations isEmpty & orEquations isEmpty)
  12204.         ifTrue: [knownValue _ true].!
  12205.  
  12206. keepTermLeft: left right: right
  12207.     "This method is used in simplifying module boolean equations. Answer true if the given term should be kept. A term has the form:
  12208.     aStrength notStronger: aWalkEquation
  12209. As a side effect, set the known value of myself (a boolean conjunction or disjunction) if possible. Assume that the sender has verified that the left side is a constant and that the right side has a constant part."
  12210.     "Since I am a conjunction (AND), I can remove all true constant terms. A false constant term makes the entire conjunction false."
  12211.  
  12212.     (left stronger: right constant)
  12213.         ifTrue:
  12214.             ["term is false, keep it and set known value"
  12215.              knownValue _ false.
  12216.              ^true]
  12217.         ifFalse:
  12218.             [(right vars isEmpty)
  12219.                 ifTrue:
  12220.                     ["term is true, don't keep it"
  12221.                      ^false]
  12222.                 ifFalse:
  12223.                     ["term value is not known, keep it"
  12224.                      ^true]].!
  12225.  
  12226. simplify
  12227.     "Simplify this equation by removing constant terms. Set known value if possible. For further details, see the comment for this method in my superclass."
  12228.  
  12229.     | equations |
  12230.     super simplify.
  12231.  
  12232.     "empty orEquations and add back only the non-constant or false ones"
  12233.     equations _ orEquations.
  12234.     orEquations _ orEquations species new.
  12235.     equations do:
  12236.         [: eqn |
  12237.          (eqn isFalse) ifTrue:
  12238.             [knownValue _ false.        "any false term makes the conjunction false"
  12239.              self addOrTerm: eqn].
  12240.          (eqn isTrue)
  12241.             ifTrue: ["don't keep true equations"]
  12242.             ifFalse:
  12243.                 ["do keep non-constant equations"
  12244.                  self addOrTerm: eqn]].
  12245.  
  12246.     self emptyCheck.    "check for empty conjunction"! !
  12247.  
  12248. BasicThingView subclass: #StandAloneThingView
  12249.     instanceVariableNames: ''
  12250.     classVariableNames: ''
  12251.     poolDictionaries: ''
  12252.     category: 'ThingLabII-UI-Thing Views'!
  12253.  
  12254.  
  12255. !StandAloneThingView methodsFor: 'controller access'!
  12256.  
  12257. defaultControllerClass
  12258.  
  12259.     ^StandAloneThingController! !
  12260.  
  12261. !StandAloneThingView methodsFor: 'displaying'!
  12262.  
  12263. display
  12264.     "First, check to see if the window has been resized. If so, fix our FrameThing (if any)."
  12265.  
  12266.     self controller reframe: self insetDisplayBox extent.
  12267.     super display.!
  12268.  
  12269. displayBorderOn: aDisplayMedium at: aPoint clippingBox: clipBox
  12270.     "Don't display a border in StandAloneThingViews."! !
  12271.  
  12272. Scene subclass: #ThingAdaptor
  12273.     instanceVariableNames: 'thing selectableGlyphs inputGlyphs historyNodes thingDatas '
  12274.     classVariableNames: ''
  12275.     poolDictionaries: ''
  12276.     category: 'ThingLabII-UI-Thing Views'!
  12277.  
  12278.  
  12279. !ThingAdaptor methodsFor: 'initialize-release'!
  12280.  
  12281. release
  12282.  
  12283.     super release.
  12284.     glyphs _ selected _ nil.! !
  12285.  
  12286. !ThingAdaptor methodsFor: 'access'!
  12287.  
  12288. name
  12289.     "Answer the name of my underlying Thing."
  12290.  
  12291.     ^thing name!
  12292.  
  12293. thing
  12294.     "Answer my underlying Thing."
  12295.  
  12296.     ^thing!
  12297.  
  12298. thing: aThing
  12299.     "Set my underlying Thing and update my caches accordingly."
  12300.  
  12301.     thing _ aThing.
  12302.     self updateCaches.!
  12303.  
  12304. thingDatas
  12305.     "Warning: thingDatasCache is a cache of my underlying Thing's ThingDatas. Care must be used to ensure that this cache is kept up to date. If in doubt, send me the message updateGlyphsCache."
  12306.  
  12307.     ^thingDatas! !
  12308.  
  12309. !ThingAdaptor methodsFor: 'glyphs access'!
  12310.  
  12311. inputGlyphs
  12312.     "Warning: inputGlyphs is a cache of my underlying Thing's input glyphs. Care must be used to ensure that this cache is kept up to date. If in doubt, send me the message updateGlyphsCache."
  12313.  
  12314.     ^inputGlyphs!
  12315.  
  12316. selectableGlyphs
  12317.     "Warning: selectableGlyphs is a cache of my underlying Thing's selectable glyphs. Care must be used to ensure that this cache is kept up to date. If in doubt, send me the message updateGlyphsCache."
  12318.  
  12319.     ^selectableGlyphs!
  12320.  
  12321. visibleGlyphs
  12322.     "Warning: glyphs is a cache of my underlying Thing's glyphs. Care must be used to ensure that this cache is kept up to date. If in doubt, send me the message updateGlyphsCache."
  12323.  
  12324.     ^glyphs! !
  12325.  
  12326. !ThingAdaptor methodsFor: 'glyphs'!
  12327.  
  12328. addGlyph: aThing
  12329.  
  12330.     self shouldNotImplement.!
  12331.  
  12332. isChanging: aThingGlyph
  12333.     "Answer true if the give glyph is undergoing changes that could effect how it is displayed."
  12334.  
  12335.     aThingGlyph glyphDependsOn do:
  12336.         [: aThing |
  12337.          (self thingIsChanging: aThing) ifTrue:
  12338.             [^true]].        "must redisplay this glyph every time"
  12339.  
  12340.     "the glyph does not depend on any changing parts"
  12341.     ^false!
  12342.  
  12343. removeGlyph: aGlyph
  12344.  
  12345.     self shouldNotImplement.! !
  12346.  
  12347. !ThingAdaptor methodsFor: 'operations'!
  12348.  
  12349. advanceHistory
  12350.     "Advance all my cached history variables."
  12351.  
  12352.     historyNodes do: [: node | node advanceHistory].!
  12353.  
  12354. updateCaches
  12355.     "Update all my caches."
  12356.  
  12357.     self clearSelection.    "clear selection"
  12358.     glyphs _ thing visibleGlyphs asOrderedCollection.
  12359.     selectableGlyphs _ thing selectableGlyphs asOrderedCollection.
  12360.     inputGlyphs _ thing inputGlyphs asOrderedCollection.
  12361.     historyNodes _ self collectHistoryThings.
  12362.     thingDatas _ self collectThingdatas.! !
  12363.  
  12364. !ThingAdaptor methodsFor: 'private'!
  12365.  
  12366. collectHistoryThings
  12367.     "Collect the history keeping subparts of my Thing."
  12368.  
  12369.     | historyThings |
  12370.     historyThings _ IdentitySet new: 30.
  12371.     thing allThingsDo: [: aThing |
  12372.         (aThing keepsHistory) ifTrue:
  12373.             [historyThings add: aThing]].
  12374.     ^historyThings asOrderedCollection!
  12375.  
  12376. collectThingdatas
  12377.     "Recompute thingDatas after a structural change."
  12378.  
  12379.     | allThingDatas |
  12380.     allThingDatas _ IdentitySet new: 100.
  12381.     thing allThingDatasInto: allThingDatas.
  12382.     ^allThingDatas asOrderedCollection select: [: td | td stay not]!
  12383.  
  12384. thingIsChanging: aThing
  12385.     "Answer true if the given Thing has a constrained part whose stay flag is not true."
  12386.  
  12387.     "if the thing has no thingDatas, then it is fixed"
  12388.     (aThing thingDatas isEmpty) ifTrue: [^false].
  12389.  
  12390.     aThing thingDatas do:
  12391.         [: thingData |
  12392.          (thingData stay not) ifTrue: [^true]].    "thing is not fixed"
  12393.     ^false    "thing is fixed"! !
  12394. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  12395.  
  12396. ThingAdaptor class
  12397.     instanceVariableNames: ''!
  12398.  
  12399.  
  12400. !ThingAdaptor class methodsFor: 'instance creation'!
  12401.  
  12402. on: aThing
  12403.  
  12404.     ^(super new) thing: aThing! !
  12405.  
  12406. Glyph subclass: #LayoutGlyph
  12407.     instanceVariableNames: 'label cost index x y '
  12408.     classVariableNames: ''
  12409.     poolDictionaries: ''
  12410.     category: 'ThingLabII-UI-Layout'!
  12411.  
  12412.  
  12413. !LayoutGlyph methodsFor: 'initialize-release'!
  12414.  
  12415. initialize
  12416.  
  12417.     super initialize.
  12418.     label _ 0.
  12419.     cost _ -1.
  12420.     index _ 0.
  12421.     x _ 0.0.
  12422.     y _ 0.0.! !
  12423.  
  12424. !LayoutGlyph methodsFor: 'accessing'!
  12425.  
  12426. cost
  12427.  
  12428.     ^cost!
  12429.  
  12430. cost: aNumber
  12431.  
  12432.     cost _ aNumber.!
  12433.  
  12434. index
  12435.     "The index field is used by PriorityQueue to keep track of element locations."
  12436.  
  12437.     ^index!
  12438.  
  12439. index: anIndex
  12440.     "The index field is used by PriorityQueue to keep track of element locations."
  12441.  
  12442.     index _ anIndex.!
  12443.  
  12444. label
  12445.  
  12446.     ^label!
  12447.  
  12448. label: aNumber
  12449.  
  12450.     label _ aNumber.!
  12451.  
  12452. x
  12453.  
  12454.     ^x!
  12455.  
  12456. x: aNumber
  12457.  
  12458.     x _ aNumber.!
  12459.  
  12460. y
  12461.  
  12462.     ^y!
  12463.  
  12464. y: aNumber
  12465.  
  12466.     y _ aNumber.! !
  12467.  
  12468. !LayoutGlyph methodsFor: 'layout support'!
  12469.  
  12470. < aVertexInfo
  12471.     "Answer true if the receiver's cost is less than the cost of the given vertex."
  12472.  
  12473.     ^cost < aVertexInfo cost!
  12474.  
  12475. > aVertexInfo
  12476.     "Answer true if the receiver's cost is greater than the cost of the given vertex."
  12477.  
  12478.     ^cost > aVertexInfo cost!
  12479.  
  12480. moveBy: deltaPoint
  12481.     "Move this vertice by the given amount."
  12482.  
  12483.     x _ x + deltaPoint x.
  12484.     y _ y + deltaPoint y.! !
  12485.  
  12486. !LayoutGlyph methodsFor: 'printing'!
  12487.  
  12488. printOn: aStream
  12489.  
  12490.     aStream nextPutAll: '(v'.
  12491.     label printOn: aStream.
  12492.     aStream nextPutAll: ' = '.
  12493.     cost printOn: aStream.
  12494.     aStream nextPut: $).! !
  12495. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  12496.  
  12497. LayoutGlyph class
  12498.     instanceVariableNames: ''!
  12499.  
  12500.  
  12501. !LayoutGlyph class methodsFor: 'instance creation'!
  12502.  
  12503. label: aNumber
  12504.     "Answer a new instance of the receiver with the given label."
  12505.  
  12506.     ^(super new) label: aNumber! !
  12507.  
  12508. SceneController subclass: #PartsBinController
  12509.     instanceVariableNames: 'currentCursor '
  12510.     classVariableNames: ''
  12511.     poolDictionaries: ''
  12512.     category: 'ThingLabII-UI-Parts Bin'!
  12513. PartsBinController comment:
  12514. 'I am a controller for PartsBinIconViews. I support PartsBin operations such as move, delete, open bin, edit icon, change name, and many more. Some of these operations are available from my menu, others through direct manipulation (dragging, double-clicking, etc).'!
  12515.  
  12516.  
  12517. !PartsBinController methodsFor: 'menu operations'!
  12518.  
  12519. addMenuItems: debugging
  12520.     "Answer my yellow-button menu given the current selection and possibly some other view or controller state. The goal is to present in the menu only those possibilities which are legal commands at this juncture. If debugging is true, present a additional options which might be useful to implementors and other gurus."
  12521.  
  12522.     | argCount arg |
  12523.     argCount _ model selected size.
  12524.     (argCount == 1)
  12525.         ifTrue: [arg _ model selected asOrderedCollection first].
  12526.  
  12527.     super addMenuItems: debugging.
  12528.  
  12529.     myMenu add: ' new thing ' action: #createThing.    
  12530.     (model isAllParts not) ifTrue:
  12531.         [myMenu add: ' new bin ' action: #createBin].
  12532.     myMenu addLine.
  12533.  
  12534.     (argCount == 1) ifTrue:
  12535.         [myMenu add: ' rename ' action: #changeName.
  12536.          myMenu add: ' edit icon ' action: #changeIcon].
  12537.     (argCount > 0) ifTrue:
  12538.         [myMenu add: ' delete ' action: #delete].
  12539.     myMenu addLine.
  12540.  
  12541.     myMenu add: ' arrange ' action: #arrange.
  12542.     myMenu add: ' update ' action: #update.
  12543.     myMenu addLine.
  12544.  
  12545.     ((argCount == 1) and: [arg holdsThing]) ifTrue:
  12546.         [myMenu add: ' explain ' action: #explainThing.
  12547.          myMenu add: ' inspect ' action: #inspectThing.
  12548.          myMenu addLine].
  12549.  
  12550.     (argCount == 1) ifTrue:
  12551.         [myMenu add: ' open ' action: #open.
  12552.         (debugging | arg holdsPartsBin) ifTrue:
  12553.             [myMenu add: ' push ' action: #enterBin]].
  12554.     (view canExit) ifTrue:
  12555.         [myMenu add: ' pop ' action: #exitBin].!
  12556.  
  12557. arrange
  12558.  
  12559.     BusyCursor begin.
  12560.     model arrangeIn: (0@0 extent: view insetDisplayBox extent).
  12561.     view computeEnclosingRectangle.
  12562.     view scrollOffset: 0@0.
  12563.     view displayScene.
  12564.     BusyCursor end.!
  12565.  
  12566. changeIcon
  12567.     "Edit the icon of the selected Thing or PartsBin."
  12568.  
  12569.     | arg |
  12570.     arg _ self argument.
  12571.     (arg notNil and: [model isAllParts | arg holdsPartsBin])
  12572.         ifTrue: [NotifyingBitEditor openOnForm: arg icon client: view]
  12573.         ifFalse: [view flash].!
  12574.  
  12575. changeName
  12576.     "Edit the name of the selected Thing or PartsBin."
  12577.  
  12578.     | arg name |
  12579.     arg _ self argument.
  12580.     (arg notNil and: [model isAllParts | arg holdsPartsBin])
  12581.         ifTrue:
  12582.             [name _ arg name.
  12583.              name _ FillInTheBlank request: 'New name?' initialAnswer: name.
  12584.              (name isEmpty not) ifTrue: [arg name: name].
  12585.              (arg name asString = name) ifFalse: [view flash]]
  12586.         ifFalse: [^view flash].
  12587.     view displayScene.!
  12588.  
  12589. createBin
  12590.     "Create a new bin named 'New Bin' and select it."
  12591.  
  12592.     | newBin |
  12593.     (model isAllParts)
  12594.         ifTrue: [^view flash].
  12595.     newBin _ PartHolder on: (PartsBin newNamed: 'New Bin').
  12596.     model
  12597.         findLocationFor: newBin
  12598.         inside: (0@0 extent: view insetDisplayBox extent).
  12599.     model addPart: newBin.
  12600.     model clearSelection.
  12601.     model select: newBin.
  12602.     view displayView.!
  12603.  
  12604. createThing
  12605.     "Create a new thing and open a ThingConstructorView on it."
  12606.  
  12607.     | newThing |
  12608.     newThing _ Thing defineNewThing.
  12609.     PartsBin changed: #creation.
  12610.     ThingConstructorView openOn: newThing.  "never returns"!
  12611.  
  12612. delete
  12613.     "Delete selected objects."
  12614.  
  12615.     | args |
  12616.     args _ model selected asOrderedCollection.
  12617.     (args isEmpty or: [(self confirm: 'Are you sure?') not])
  12618.         ifTrue: [^self].
  12619.     args do: [: p |
  12620.         "don't delete AllParts from Top Bin"
  12621.         ((p holdsAllParts) & (model name == 'Top Bin'))
  12622.             ifTrue: [view flash]
  12623.             ifFalse:
  12624.                 ["remove the thing or parts bin from this parts bin"
  12625.                  model deselect: p.
  12626.                  model removeGlyph: p.
  12627.                  "if my model is an All Parts bin, try to remove the deleted thing from the system entirely"
  12628.                   (model isAllParts & p holdsThing) ifTrue:
  12629.                     [(p cargo destroyAndRemoveClass) ifFalse:
  12630.                         [self error: 'Could not destroy ', p cargo name]]]].
  12631.     view displayView.
  12632.     PartsBin changed: #deletion.!
  12633.  
  12634. enterBin
  12635.     "The selection must be a PartsBin. Make the current view a view on this PartsBin."
  12636.  
  12637.     | arg |
  12638.     arg _ self argument.
  12639.     (arg notNil and: [arg holdsPartsBin])
  12640.         ifTrue: [view enter: arg cargo]
  12641.         ifFalse: [^view flash].
  12642.     view displayScene.!
  12643.  
  12644. exitBin
  12645.     "Undo the effect of the last 'enter' operation."
  12646.  
  12647.     (view canExit) ifFalse: [^view flash].
  12648.     view exit.
  12649.     view displayScene.!
  12650.  
  12651. explainThing
  12652.     "Open an editor on the explanation of the selected Thing."
  12653.  
  12654.     | arg fromFrame |
  12655.     arg _ self argument.
  12656.     (arg notNil and: [arg holdsThing])
  12657.         ifFalse: [^view flash].
  12658.     fromFrame _ arg boundingBox translateBy:
  12659.                     (view modelToDisplayPoint: 0@0).
  12660.     Explanation openOn: arg cargo zoomingFrom: fromFrame.!
  12661.  
  12662. inspectThing
  12663.     "Inspect the currently selected Thing."
  12664.  
  12665.     | arg |
  12666.     arg _ self argument.
  12667.     (arg notNil and: [arg holdsThing])
  12668.         ifTrue: [arg cargo inspect]
  12669.         ifFalse: [view flash].!
  12670.  
  12671. open
  12672.     "Open a new view on the currently selected Thing or PartsBin."
  12673.  
  12674.     | arg fromFrame |
  12675.     arg _ self argument.
  12676.     (arg notNil and: [arg cargo notNil])
  12677.         ifFalse: [^view flash].
  12678.     fromFrame _ arg boundingBox translateBy:
  12679.                     (view modelToDisplayPoint: 0@0).
  12680.     (arg holdsPartsBin)
  12681.         ifTrue: [
  12682.             PartsBinView
  12683.                 openOn: arg cargo
  12684.                 from: arg
  12685.                 zoomingFrom: fromFrame
  12686.                 to: arg lastFrame]
  12687.         ifFalse: [    
  12688.             ThingConstructorView
  12689.                 openOn: arg cargo
  12690.                 from: arg
  12691.                 zoomingFrom: fromFrame
  12692.                 to: arg lastFrame].!
  12693.  
  12694. update
  12695.  
  12696.     view syncWithReality.
  12697.     view displayView.! !
  12698.  
  12699. !PartsBinController methodsFor: 'direct manipulation'!
  12700.  
  12701. deposit: movingParts at: relativePositions relativeTo: aPoint orginallyAt: originalPositions copyFlag: copyFlag
  12702.     "Deposit moving parts in the view containing aPoint if it is one of ours. Otherwise, complete a move operation within this view. When this method is invoked, the parts have already been dragged in this view, so if we are copying into another view, we must move the copies in this view back to their original positions."
  12703.  
  12704.     | destTopView destView |
  12705.     "Are we moving parts to another view?"
  12706.     destTopView _ self destinationTopView.
  12707.     (destTopView isNil)
  12708.         ifTrue:        "no, moving within this view"
  12709.             [view shiftOrigin; displayView]
  12710.         ifFalse:        "yes, copying to another view"
  12711.             ["first, undo the part moving that we did in this view"
  12712.              movingParts
  12713.                 with: originalPositions
  12714.                 do: [: p : originalPos | p location: originalPos].
  12715.              view displayView.
  12716.              "then copy the parts to the destination view "
  12717.              destView _ self destinationAt: aPoint in: destTopView.
  12718.              destView
  12719.                 acceptCopies: movingParts
  12720.                 at: relativePositions
  12721.                 withRespectTo: aPoint.
  12722.              "bring destination view forward and display it with the new parts"
  12723.              destTopView displaySafe: [destView displayView].
  12724.              copyFlag    "if copyFlag is false, this is a move between bins"
  12725.                 ifFalse: [self delete]].!
  12726.  
  12727. doubleClickAt: aPoint
  12728.     "Handle a double-click action by trying to open the object under aPoint. A double-click that is not over an icon does a selectAll."
  12729.  
  12730.     ((self glyphAt: aPoint) isNil)
  12731.         ifTrue:
  12732.             [self selectAll.
  12733.              sensor waitNoButton]
  12734.         ifFalse:
  12735.             [model clearSelection.
  12736.              self selectAt: aPoint toggleFlag: false.
  12737.              view displayScene.
  12738.              (sensor leftShiftDown)
  12739.                 ifTrue: [self enterBin]
  12740.                 ifFalse: [self open]].!
  12741.  
  12742. moveAt: aPoint
  12743.     "Drag all selected parts for a move or copy operation. If the destination view is different than my view, then this is a copy operation. Otherwise, the parts are simply moved."
  12744.  
  12745.     | movingParts relativePositions copyFlag oldPositions point oldPoint |
  12746.     movingParts _ model selected asOrderedCollection.
  12747.     model moveToFront: movingParts.
  12748.     relativePositions _ movingParts collect: [: p | p location - aPoint].
  12749.     copyFlag _ sensor leftShiftDown not.
  12750.     oldPositions _ movingParts collect: [: p | p location].
  12751.     view computeBackground.
  12752.     [sensor redButtonPressed] whileTrue:
  12753.         [point _ sensor cursorPoint.
  12754.          (point ~= oldPoint) ifTrue:
  12755.             [movingParts
  12756.                 with: relativePositions
  12757.                 do: [: p : relPos | p location: (relPos + point)].
  12758.              self doCursorFeedback.
  12759.              view displayFeedback]].
  12760.     self
  12761.         deposit: movingParts at: relativePositions
  12762.         relativeTo: sensor cursorPoint
  12763.         orginallyAt: oldPositions
  12764.         copyFlag: copyFlag.
  12765.     Cursor normal show.! !
  12766.  
  12767. !PartsBinController methodsFor: 'private'!
  12768.  
  12769. destinationAt: aPoint in: aView
  12770.     "Answer a view that can accept icons under the given point in the given top view."
  12771.  
  12772.     aView subViews do:
  12773.         [: subView |
  12774.          ((subView containsPoint: aPoint) and:
  12775.           [(subView isMemberOf: PartsBinView) |
  12776.            (subView isMemberOf: ThingConstructorView) |
  12777.            (subView isMemberOf: MultiThingView)])
  12778.                 ifTrue: [^subView]].
  12779.     ^nil!
  12780.  
  12781. destinationTopView
  12782.     "Answer the top view of the destination for a move or copy between views. Answer nil if the destination is myself or if there is no appropriate destination under the cursor."
  12783.  
  12784.     | point aTopView |
  12785.     (self viewHasCursor) ifTrue: [^nil].
  12786.     point _ sensor cursorPoint.
  12787.     ScheduledControllers scheduledControllers do:
  12788.         [: c | ((self destinationAt: point in: (c view)) notNil)
  12789.                  ifTrue: [^c view]].
  12790.     ^nil!
  12791.  
  12792. doCursorFeedback
  12793.     "Show a bull's eye cursor if we are over a view that could be the destination for this move operation. Show the normal cursor otherwise."
  12794.  
  12795.     (self destinationTopView isNil)
  12796.         ifTrue: [(currentCursor ~~ Cursor normal)
  12797.             ifTrue: [(currentCursor _ Cursor normal) show]]
  12798.         ifFalse: [(currentCursor ~~ Cursor bull)
  12799.             ifTrue: [(currentCursor _ Cursor bull) show]].! !
  12800.  
  12801. SceneController subclass: #BasicThingController
  12802.     instanceVariableNames: 'editConstraints plan running '
  12803.     classVariableNames: ''
  12804.     poolDictionaries: ''
  12805.     category: 'ThingLabII-UI-Thing Views'!
  12806. BasicThingController comment:
  12807. 'This is the controller class for BasicThingControllers.'!
  12808.  
  12809.  
  12810. !BasicThingController methodsFor: 'initialize-release'!
  12811.  
  12812. initialize
  12813.  
  12814.     super initialize.
  12815.     editConstraints _ OrderedCollection new.
  12816.     plan _ Plan new.
  12817.     running _ false.! !
  12818.  
  12819. !BasicThingController methodsFor: 'control defaults'!
  12820.  
  12821. controlActivity
  12822.     "Process user mouse and keyboard activity."
  12823.  
  12824.     super controlActivity.
  12825.     "if running is true, advance history variables"
  12826.     running ifTrue: [self executeAndRedisplay].! !
  12827.  
  12828. !BasicThingController methodsFor: 'menu operations'!
  12829.  
  12830. addMenuItems: debugging
  12831.     "Answer my yellow-button menu given the current selection and possibly some other view or controller state. The goal is to present in the menu only those possibilities which are legal commands at this juncture. If debugging is true, present a additional options which might be useful to implementors and other gurus."
  12832.  
  12833.     | argCount |
  12834.     argCount _ model selected size.
  12835.  
  12836.     "add superclass menu items"
  12837.     super addMenuItems: debugging.
  12838.  
  12839.     (running)
  12840.         ifTrue:
  12841.             [myMenu add: ' stop ' action: #stop]
  12842.         ifFalse:
  12843.             [myMenu add: ' step ' action: #step.
  12844.              myMenu add: ' run ' action: #run].
  12845.     myMenu addLine.
  12846.  
  12847.     (argCount <= 1) ifTrue:
  12848.         [myMenu add: ' explain ' action: #explain.
  12849.          myMenu add: ' inspect ' action: #inspectThing].
  12850.     myMenu add: ' debugger ' action: #openDebugger.
  12851.     myMenu addLine.!
  12852.  
  12853. explain
  12854.     "If a single part is selected, explain that part. Otherwise, explain the top-level Thing (the Thing under construction)."
  12855.  
  12856.     (self argument notNil)
  12857.         ifTrue: [Explanation openOn: self argument]
  12858.         ifFalse: [Explanation openOn: model thing].!
  12859.  
  12860. inspectThing
  12861.     "If a single part is selected, inspect that part. Otherwise, inspect the top-level Thing (the Thing under construction)."
  12862.  
  12863.     (self argument notNil)
  12864.         ifTrue: [self argument inspect]
  12865.         ifFalse: [model thing inspect].!
  12866.  
  12867. openDebugger
  12868.     "Open a ThingDebugView on my Thing."
  12869.  
  12870.     ThingDebugView openOn: model thing.!
  12871.  
  12872. run
  12873.     "Allow history to advance as fast as it can be computed."
  12874.  
  12875.     self makePlan.
  12876.     running _ true.!
  12877.  
  12878. step
  12879.     "Advance history one tick."
  12880.  
  12881.     self run.
  12882.     self executeAndRedisplay.
  12883.     self stop.!
  12884.  
  12885. stop
  12886.     "Stop the clock!!"
  12887.  
  12888.     running _ false.! !
  12889.  
  12890. !BasicThingController methodsFor: 'direct manipulation'!
  12891.  
  12892. doubleClickAt: aPoint
  12893.     "Handle a double-click action by opening an inspector on the object under aPoint or, if aPoint is not over any glyph, selecting everything."
  12894.  
  12895.     ((self glyphAt: aPoint) isNil)
  12896.         ifTrue:
  12897.             [self selectAll.
  12898.              sensor waitNoButton]
  12899.         ifFalse:
  12900.             [model clearSelection.
  12901.              self selectAt: aPoint toggleFlag: false.
  12902.              view displayScene.
  12903.              self inspectThing].!
  12904.  
  12905. moveAt: aPoint
  12906.     "Move all selected parts. If only one part is being moved, try to merge it with the part (if any) at its new location."
  12907.  
  12908.     | parts partLocations |
  12909.     parts _ model selected asOrderedCollection.
  12910.     partLocations _ parts collect: [: p | p location].
  12911.     self
  12912.         while: [sensor anyButtonPressed]
  12913.         move: partLocations
  12914.         refPoint: aPoint.
  12915.     view computeEnclosingRectangle.
  12916.     view displayView.!
  12917.  
  12918. while: testBlock move: pointThings refPoint: refPoint
  12919.     "Move the given PointThings. Any glyphs attached to the points will follow the mouse until a button is pressed."
  12920.  
  12921.     | relativePositions point oldPoint |
  12922.     relativePositions _ pointThings collect: [: p | p asPoint - refPoint].
  12923.     self addMouseConstraintsFor: pointThings with: relativePositions.
  12924.     [testBlock value] whileTrue:
  12925.         [point _ sensor cursorPoint.
  12926.          (oldPoint ~= sensor cursorPoint) ifTrue:
  12927.             [self executeAndRedisplay]].
  12928.     self removeMouseConstraints.! !
  12929.  
  12930. !BasicThingController methodsFor: 'editor support'!
  12931.  
  12932. acceptChange
  12933.     "This message is sent by an editor when state of Thing being edited is accepted."
  12934.  
  12935.     view displaySafe: [self executeAndRedisplay].!
  12936.  
  12937. doneEditing
  12938.     "This message is sent by an editor when it is done editing and is about to be closed."
  12939.  
  12940.     self removeInputConstraints.! !
  12941.  
  12942. !BasicThingController methodsFor: 'keyboard'!
  12943.  
  12944. readKeyboard
  12945.     "Keystrokes are sent to all selected Things that are interested in keyboard input."
  12946.  
  12947.     | interested char |
  12948.     editConstraints _ editConstraints species new.
  12949.     interested _ model selected select:
  12950.         [: thing |
  12951.          (thing wantsKeystrokes) and: [model inputGlyphs includes: thing]].
  12952.     interested do:
  12953.         [: thing | self addInputConstraints: thing keystrokeConstraints].
  12954.     (self cannotEditThing) ifTrue:
  12955.         [sensor keyboard. "flush input character"
  12956.         ^self abortInput].
  12957.  
  12958.     self makePlan.
  12959.     [sensor keyboardPressed] whileTrue:
  12960.         [char _ sensor keyboard.
  12961.          interested do: [: thing | thing handleKeystroke: char view: view].
  12962.          self executeAndRedisplay].
  12963.     self removeInputConstraints.! !
  12964.  
  12965. !BasicThingController methodsFor: 'mouse'!
  12966.  
  12967. passMouseTo: thing
  12968.     "Allow the given Thing to handle a mouse interaction. It is assumed that the given Thing wants the mouse."
  12969.  
  12970.     editConstraints _ editConstraints species new.
  12971.     self addInputConstraints: thing mouseConstraints.
  12972.     (self cannotEditThing) ifTrue:
  12973.         [^self abortInput].
  12974.  
  12975.     self makePlan.
  12976.     thing handleMouseDown: self adjustedCursorPoint view: view.
  12977.     thing handleMouseMove: self adjustedCursorPoint view: view.    
  12978.     self executeAndRedisplay.
  12979.     [sensor anyButtonPressed] whileTrue:
  12980.         [thing handleMouseMove: self adjustedCursorPoint view: view.
  12981.          self executeAndRedisplay].
  12982.     thing handleMouseUp: self adjustedCursorPoint view: view.
  12983.     self executeAndRedisplay.
  12984.     self removeInputConstraints.! !
  12985.  
  12986. !BasicThingController methodsFor: 'constraints'!
  12987.  
  12988. abortInput
  12989.     "An input constraint could not be satisfied. Flash the view and abort."
  12990.  
  12991.     view flash.
  12992.     editConstraints do: [: c | c removeConstraint. c destroy].
  12993.     editConstraints _ editConstraints species new.
  12994.     running ifTrue: [self makePlan].!
  12995.  
  12996. addInputConstraints: constraintsList
  12997.     "Add the given list of constraints and remember them in editConstraints."
  12998.  
  12999.     constraintsList do:
  13000.         [: c |
  13001.          c addConstraint.
  13002.          editConstraints add: c].!
  13003.  
  13004. addMouseConstraintsFor: movingParts with: offsets 
  13005.     "Add mouse constraints (which are special user input constraints) for the given collection of parts at the associated offsets from the mouse position."
  13006.  
  13007.     | part offset |
  13008.     editConstraints _ editConstraints species new.
  13009.     1 to: movingParts size do:  [: i | 
  13010.         part _ movingParts at: i.
  13011.         offset _ offsets at: i.
  13012.         editConstraints add:
  13013.             (XMouseConstraint
  13014.                 ref: part->#x
  13015.                 strength: (ThingLabII editStrength)
  13016.                 offset: offset x).
  13017.         editConstraints add:
  13018.             (YMouseConstraint
  13019.                 ref: part->#y
  13020.                 strength: (ThingLabII editStrength)
  13021.                 offset: offset y)].
  13022.     editConstraints do: [: c | c addConstraint].
  13023.     self makePlan.!
  13024.  
  13025. cannotEditThing
  13026.     "Answer true if any of the edit constraints is not satisfied."
  13027.  
  13028.     editConstraints do: [: c |
  13029.         (c isSatisfied) ifFalse: [^true]].
  13030.     ^false!
  13031.  
  13032. executeAndRedisplay
  13033.     "Advance history if necessary, execute the plan, and display new state."
  13034.  
  13035.     running ifTrue: [model advanceHistory].
  13036.     plan execute.    
  13037.     view displayFeedback.!
  13038.  
  13039. makePlan
  13040.     "Plan for constraint satisfaction and redisplay. This includes making a constraint satisfaction plan, computing the model's fixed glyphs, and computing the background form for redisplay."
  13041.  
  13042.     | allThingDatas c |
  13043.     allThingDatas _ model thingDatas copy.
  13044.     editConstraints do:
  13045.         [: c |
  13046.          (c isSatisfied) ifTrue:
  13047.             [c outDatasDo:
  13048.                 [: out | allThingDatas add: out]]].
  13049.     plan _ DeltaBluePlanner
  13050.             extractPlanFromChangingThingDatas: allThingDatas.
  13051.     view computeBackground.!
  13052.  
  13053. removeInputConstraints
  13054.  
  13055.     model advanceHistory.
  13056.     editConstraints do: [: c | c removeConstraint. c destroy].
  13057.     editConstraints _ editConstraints species new.
  13058.     self makePlan.
  13059.     self executeAndRedisplay.!
  13060.  
  13061. removeInputConstraints: constraintsList
  13062.     "Remove the given list of constraints but do not replan."
  13063.  
  13064.     constraintsList do:
  13065.         [: c |
  13066.          c removeConstraint.
  13067.          editConstraints remove: c.
  13068.          c destroy].!
  13069.  
  13070. removeMouseConstraints
  13071.     "Just provides a more mnemonic name for this function when used with mouse constraints."
  13072.  
  13073.     self removeInputConstraints.! !
  13074.  
  13075. Glyph subclass: #ButtonGlyph
  13076.     instanceVariableNames: 'form action lastMouseInButton '
  13077.     classVariableNames: ''
  13078.     poolDictionaries: ''
  13079.     category: 'ThingLabII-UI-Framework'!
  13080.  
  13081.  
  13082. !ButtonGlyph methodsFor: 'initialize-release'!
  13083.  
  13084. initialize
  13085.  
  13086.     super initialize.
  13087.     self form: ' Push Me!! ' asParagraph asForm.
  13088.     action _ nil.! !
  13089.  
  13090. !ButtonGlyph methodsFor: 'accessing'!
  13091.  
  13092. action: aBlock
  13093.  
  13094.     action _ aBlock.!
  13095.  
  13096. form
  13097.  
  13098.     ^form!
  13099.  
  13100. form: aForm
  13101.  
  13102.     aForm offset: (aForm computeBoundingBox extent // -2).
  13103.     form _ aForm.! !
  13104.  
  13105. !ButtonGlyph methodsFor: 'glyph protocol'!
  13106.  
  13107. boundingBox
  13108.     "Answer my bounding box."
  13109.  
  13110.     ^form computeBoundingBox translateBy: (location + form offset)!
  13111.  
  13112. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox
  13113.  
  13114.     form
  13115.         displayOn: aDisplayMedium
  13116.         at: location + aDisplayPoint
  13117.         clippingBox: clipBox
  13118.         rule: (Form over)
  13119.         mask: (Form black).! !
  13120.  
  13121. !ButtonGlyph methodsFor: 'mouse'!
  13122.  
  13123. handleMouseDown: mousePoint view: view
  13124.     "Give feedback that the button has been pressed. The action is invoked only if the mouse goes up inside the button."
  13125.  
  13126.     self reverseIn: view.
  13127.     lastMouseInButton _ true.!
  13128.  
  13129. handleMouseMove: mousePoint view: view
  13130.     "Show feedback. If the mouse is in the button, show it reversed."
  13131.  
  13132.     | mouseInButton |
  13133.     mouseInButton _ self containsPoint: mousePoint.
  13134.     (mouseInButton ~= lastMouseInButton) ifTrue:
  13135.         [self reverseIn: view.
  13136.          lastMouseInButton _ mouseInButton].!
  13137.  
  13138. handleMouseUp: mousePoint view: view
  13139.     "If the mouse is still in the button, then invoke the action, unless it is nil, in which case do nothing."
  13140.  
  13141.     (self containsPoint: mousePoint) ifTrue:
  13142.         [lastMouseInButton ifTrue: [self reverseIn: view].
  13143.          (action notNil) ifTrue:
  13144.             [action value: view]].
  13145.     view displayScene.!
  13146.  
  13147. reverseIn: view
  13148.     "Show feedback by reversing. This toggles the reverse mode, so calling this method twice returns the display to its original state."
  13149.  
  13150.     Display reverse: 
  13151.         ((self boundingBox translateBy: (view modelToDisplayPoint: 0@0))
  13152.             intersect: view insetDisplayBox).!
  13153.  
  13154. wantsMouse
  13155.  
  13156.     ^true! !
  13157. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  13158.  
  13159. ButtonGlyph class
  13160.     instanceVariableNames: ''!
  13161.  
  13162.  
  13163. !ButtonGlyph class methodsFor: 'instance creation'!
  13164.  
  13165. at: aPoint form: aForm
  13166.  
  13167.     ^(self new) location: aPoint; form: aForm! !
  13168.  
  13169. SceneView subclass: #PartsBinView
  13170.     instanceVariableNames: 'path '
  13171.     classVariableNames: ''
  13172.     poolDictionaries: ''
  13173.     category: 'ThingLabII-UI-Parts Bin'!
  13174. PartsBinView comment:
  13175. 'I am a view used to display a two-dimensional layout of part icons. Each icon has a location and a name and is capable of displaying itself. PartsBin is my model and PartsBinIconController is my controller.'!
  13176.  
  13177.  
  13178. !PartsBinView methodsFor: 'initialize-release'!
  13179.  
  13180. initialize
  13181.  
  13182.     super initialize.
  13183.     path _ OrderedCollection new.
  13184.     PartsBin addDependent: self.!
  13185.  
  13186. release
  13187.  
  13188.     PartsBin removeDependent: self.! !
  13189.  
  13190. !PartsBinView methodsFor: 'controller access'!
  13191.  
  13192. defaultControllerClass
  13193.  
  13194.     ^PartsBinController! !
  13195.  
  13196. !PartsBinView methodsFor: 'operations'!
  13197.  
  13198. acceptCopies: partsCollection at: relPoints withRespectTo: aPoint
  13199.     "Accept copies of the given collections of parts. Each part should be placed at the location given by the corresponding element of the relPoints collection, relative to the given point."
  13200.  
  13201.     | parts refPoint |
  13202.     (model isAllParts) ifTrue: [^self flash].
  13203.     parts _ partsCollection collect: [: p | p copy].
  13204.     refPoint _ aPoint - self insetDisplayBox origin.
  13205.     parts with: relPoints do:
  13206.         [: p : relLoc | model addPart: p at: (refPoint + relLoc)].
  13207.     self shiftOrigin.!
  13208.  
  13209. canExit
  13210.  
  13211.     ^path isEmpty not!
  13212.  
  13213. enter: aPartsBin
  13214.  
  13215.     path addLast: model.
  13216.     self model: aPartsBin.
  13217.     self newLabel: aPartsBin name.
  13218.     self computeEnclosingRectangle.
  13219.     self scrollOffset: 0@0.!
  13220.  
  13221. exit
  13222.  
  13223.     (path isEmpty) ifTrue: [^self flash].
  13224.     self model: path removeLast.
  13225.     self newLabel: self model name.
  13226.     self computeEnclosingRectangle.
  13227.     self scrollOffset: 0@0.! !
  13228.  
  13229. !PartsBinView methodsFor: 'updating'!
  13230.  
  13231. doneEditingForm
  13232.     "Sent by a NotifyingBitEditor when it is done editing a part icon. This event is not interesting to me."!
  13233.  
  13234. formChanged
  13235.     "Sent by a NotifyingBitEditor when one of my part's icons has been
  13236. edited."
  13237.  
  13238.     self displaySafe: [self displayScene].!
  13239.  
  13240. shiftOrigin
  13241.     "Move all my glyphs so that they have positive locations."
  13242.  
  13243.     | adjustment |
  13244.     self computeEnclosingRectangle.
  13245.     adjustment _ (self enclosingRectangle origin) min: 0@0.
  13246.     (adjustment ~= (0@0))
  13247.         ifTrue:
  13248.             [(model allGlyphs) do:
  13249.                 [: p | p location: (p location - adjustment)]].
  13250.     self computeEnclosingRectangle.!
  13251.  
  13252. syncWithReality
  13253.     "Update model from the underlying Thing database."
  13254.  
  13255.     ^model syncWithReality: (0@0 corner: self insetDisplayBox extent)!
  13256.  
  13257. update: change
  13258.  
  13259.     (change == #deletion)
  13260.         ifTrue:
  13261.             [((self syncWithReality) and:
  13262.               [self topView isVisible]) ifTrue:
  13263.                 [^self displaySafe: [self displayView]]].
  13264.     ((change == #creation) & (model isAllParts))
  13265.         ifTrue:
  13266.             [((self syncWithReality) and:
  13267.               [self topView isVisible]) ifTrue:
  13268.                 [^self displaySafe: [self displayView]]].! !
  13269. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  13270.  
  13271. PartsBinView class
  13272.     instanceVariableNames: ''!
  13273.  
  13274.  
  13275. !PartsBinView class methodsFor: 'instance creation'!
  13276.  
  13277. openOn: aPartsBin
  13278.     "Open a view on the given parts bin."
  13279.  
  13280.     aPartsBin syncWithReality: nil.
  13281.     aPartsBin clearSelection.
  13282.     self
  13283.         openWithSubview: ((PartsBinView new) model: aPartsBin)
  13284.         label: (aPartsBin name)!
  13285.  
  13286. openOn: aPartsBin from: aPartHolder zoomingFrom: fromRect to: openFrame
  13287.     "Open a view on the given parts bin zooming from fromRect to openFrame. Remember that this view was opened from the given partHolder."
  13288.  
  13289.     aPartsBin syncWithReality: openFrame.
  13290.     aPartsBin clearSelection.
  13291.     self
  13292.         openWithSubview: ((PartsBinView new) model: aPartsBin)
  13293.         label: (aPartsBin name)
  13294.         fromHolder: aPartHolder
  13295.         zoomFrom: fromRect 
  13296.         to: openFrame.! !
  13297.  
  13298. Glyph subclass: #IconGlyph
  13299.     instanceVariableNames: 'nameForm '
  13300.     classVariableNames: ''
  13301.     poolDictionaries: ''
  13302.     category: 'ThingLabII-UI-Framework'!
  13303. IconGlyph comment:
  13304. 'This is an abstract class for a special kind of Glyph that displays an icon with a centered text label below it. Subclasses must respond to these messages:
  13305.     name
  13306.     name:
  13307.     icon
  13308.     icon:
  13309.  
  13310. I cache a Form for my name in the instance variable ''nameForm'' for more efficient display. My subclasses must update this cache whenever their name changes by sending the message updateNameIcon to self.'!
  13311.  
  13312.  
  13313. !IconGlyph methodsFor: 'initialize-release'!
  13314.  
  13315. initialize
  13316.     "Use a dummy Form until nameForm can be updated from the actual object name."
  13317.  
  13318.     super initialize.
  13319.     nameForm _ Form extent: (10@12).! !
  13320.  
  13321. !IconGlyph methodsFor: 'accessing'!
  13322.  
  13323. icon
  13324.  
  13325.     ^self subclassResponsibility!
  13326.  
  13327. icon: aForm
  13328.  
  13329.     ^self subclassResponsibility!
  13330.  
  13331. name
  13332.  
  13333.     ^self subclassResponsibility!
  13334.  
  13335. name: aString
  13336.     "Note: after changing my name, send myself the message 'updateNameForm'."
  13337.  
  13338.     ^self subclassResponsibility!
  13339.  
  13340. updateNameForm
  13341.     "For efficiency, I cache a Form containing the bitmap for the text of my name."
  13342.  
  13343.     nameForm _
  13344.         (Paragraph
  13345.             withText: self name asText
  13346.             style: ((TextStyle default) lineGrid: 12; baseline: 9)) centered asForm.! !
  13347.  
  13348. !IconGlyph methodsFor: 'glyph protocol'!
  13349.  
  13350. boundingBox
  13351.     "Answer my bounding box."
  13352.  
  13353.     ^self iconBox merge: self nameBox!
  13354.  
  13355. containsPoint: aPoint
  13356.     "Answer true if either my icon or name boxes contains the given point. Allow a little slop around the icon box."
  13357.  
  13358.     ^(((self iconBox) expandBy: 2) containsPoint: aPoint) or:
  13359.       [(self nameBox) containsPoint: aPoint]!
  13360.  
  13361. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox
  13362.  
  13363.     self icon
  13364.         displayOn: aDisplayMedium
  13365.         at: (aDisplayPoint + self iconOffset)
  13366.         clippingBox: clipBox
  13367.         rule: (Form over)
  13368.         mask: (Form black).
  13369.  
  13370.     nameForm
  13371.         displayOn: aDisplayMedium
  13372.         at: (aDisplayPoint + self nameOffset)
  13373.         clippingBox: clipBox
  13374.         rule: (Form over)
  13375.         mask: (Form black).!
  13376.  
  13377. highlightOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox
  13378.  
  13379.     aDisplayMedium
  13380.         border: ((self iconBox translateBy: aDisplayPoint) expandBy: 1)
  13381.         widthRectangle: (1@1 corner: 1@1)
  13382.         mask: (Form gray)
  13383.         clippingBox: clipBox.
  13384.  
  13385.     nameForm
  13386.         displayOn: aDisplayMedium
  13387.         at: (aDisplayPoint + self nameOffset)
  13388.         clippingBox: clipBox
  13389.         rule: 12
  13390.         mask: (Form black).! !
  13391.  
  13392. !IconGlyph methodsFor: 'private'!
  13393.  
  13394. iconBox
  13395.     "Answer my icon bounding box."
  13396.  
  13397.     ^self icon computeBoundingBox translateBy: self iconOffset!
  13398.  
  13399. iconOffset
  13400.     "Center my icon on my location."
  13401.  
  13402.     ^location - (self icon extent // 2)!
  13403.  
  13404. nameBox
  13405.     "Answer my name bounding box."
  13406.  
  13407.     ^nameForm computeBoundingBox translateBy: self nameOffset!
  13408.  
  13409. nameOffset
  13410.     "Center my nameForm under my icon."
  13411.  
  13412.     ^location +
  13413.         ((nameForm width negated // 2)@((self icon height // 2) + 2))! !
  13414.  
  13415. Glyph subclass: #ArrowHead
  13416.     instanceVariableNames: 'vector '
  13417.     classVariableNames: 'FormTable '
  13418.     poolDictionaries: ''
  13419.     category: 'ThingLabII-UI-Debugger'!
  13420.  
  13421.  
  13422. !ArrowHead methodsFor: 'glyph protocol'!
  13423.  
  13424. boundingBox
  13425.     "Answer my bounding box."
  13426.  
  13427.     | form |
  13428.     form _ self form.
  13429.     ^form computeBoundingBox
  13430.          translateBy: (location + form offset)!
  13431.  
  13432. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox
  13433.     "Display myself."
  13434.  
  13435.     self form
  13436.         displayOn: aDisplayMedium
  13437.         at: aDisplayPoint + location
  13438.         clippingBox: clipBox
  13439.         rule: Form paint
  13440.         mask: Form black.!
  13441.  
  13442. form
  13443.     "Answer the arrowhead form for my vector."
  13444.  
  13445.     | slope absSlope angle |
  13446.     (vector x = 0) ifTrue:
  13447.         [(vector y >= 0)
  13448.             ifTrue: [^FormTable at: 270]
  13449.             ifFalse: [^FormTable at: 90]].
  13450.  
  13451.     slope _ vector y negated asFloat / vector x asFloat.
  13452.     absSlope _ slope abs.
  13453.     (absSlope < 0.5) ifTrue: [angle _ 0].
  13454.     ((absSlope >= 0.5) & (absSlope < 2.0)) ifTrue: [angle _ 45].
  13455.     (absSlope >= 2.0) ifTrue: [angle _ 90].
  13456.     (slope > 0)
  13457.         ifTrue:
  13458.             [(vector x > 0)
  13459.                 ifTrue: [^FormTable at: 0 + angle]
  13460.                 ifFalse: [^FormTable at: 180 + angle]]
  13461.         ifFalse:
  13462.             [(vector x < 0)
  13463.                 ifTrue: [^FormTable at: 180 - angle]
  13464.                 ifFalse: [^FormTable at: 360 - angle]].! !
  13465.  
  13466. !ArrowHead methodsFor: 'access'!
  13467.  
  13468. vector: vectorPoint
  13469.     "Set my vector. The vector is used to choose an arrowhead with the right orientation."
  13470.  
  13471.     vector _ vectorPoint.! !
  13472. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  13473.  
  13474. ArrowHead class
  13475.     instanceVariableNames: ''!
  13476.  
  13477.  
  13478. !ArrowHead class methodsFor: 'class initialization'!
  13479.  
  13480. initialize
  13481.     "Build my table of arrowhead forms."
  13482.     "ArrowHead initialize"
  13483.  
  13484.     FormTable _ Dictionary new.
  13485.     FormTable at: 0 put:                            "0 degrees"
  13486.         (Form
  13487.             extent: 7@7
  13488.             fromArray: #(32768 24576 14336 65024 14336 24576 32768)
  13489.             offset: 0@-3).
  13490.     FormTable at: 45 put:                            "45 degrees"
  13491.         (Form
  13492.             extent: 7@7
  13493.             fromArray: #(512 3072 15360 63488 14336 20480 36864)
  13494.             offset: 0@-6).
  13495.     FormTable at: 90 put:                            "90 degrees"
  13496.         (Form
  13497.             extent: 7@7
  13498.             fromArray: #(4096 4096 14336 14336 31744 21504 37376)
  13499.             offset: -3@-6).
  13500.     FormTable at: 135 put:                        "135 degrees"
  13501.         (Form
  13502.             extent: 7@7
  13503.             fromArray: #(32768 24576 30720 15872 14336 5120 4608)
  13504.             offset: -6@-6).
  13505.     FormTable at: 180 put:                        "180 degrees"
  13506.         (Form
  13507.             extent: 7@7
  13508.             fromArray: #(512 3072 14336 65024 14336 3072 512)
  13509.             offset: -6@-3).
  13510.     FormTable at: 225 put:                        "225 degrees"
  13511.         (Form
  13512.             extent: 7@7
  13513.             fromArray: #(4608 5120 14336 15872 30720 24576 32768)
  13514.             offset: -6@0).
  13515.     FormTable at: 270 put:                        "270 degrees"
  13516.         (Form
  13517.             extent: 7@7
  13518.             fromArray: #(37376 21504 31744 14336 14336 4096 4096)
  13519.             offset: -3@0).
  13520.     FormTable at: 315 put:                        "315 degrees"
  13521.         (Form
  13522.             extent: 7@7
  13523.             fromArray: #(36864 20480 14336 63488 15360 3072 512)
  13524.             offset: 0@0).
  13525.     FormTable at: 360 put: (FormTable at: 0).        "360 is same as 0 degrees"! !
  13526.  
  13527. !ArrowHead class methodsFor: 'instance creation'!
  13528.  
  13529. at: aPoint vector: vectorPoint
  13530.     "Create a new instance with the given orientation (determined by vectorPoint) and location."
  13531.  
  13532.     ^(super new)
  13533.         vector: vectorPoint;
  13534.         location: aPoint! !
  13535.  
  13536.  
  13537. BasicThingController subclass: #ThingConstructorController
  13538.     instanceVariableNames: 'lastInserted '
  13539.     classVariableNames: ''
  13540.     poolDictionaries: ''
  13541.     category: 'ThingLabII-UI-Thing Views'!
  13542. ThingConstructorController comment:
  13543. 'This is the controller class for ThingConstructorViews.'!
  13544.  
  13545.  
  13546. !ThingConstructorController methodsFor: 'initialize-release'!
  13547.  
  13548. initialize
  13549.  
  13550.     super initialize.
  13551.     lastInserted _ nil.! !
  13552.  
  13553. !ThingConstructorController methodsFor: 'menu operations'!
  13554.  
  13555. addMenuItems: debugging
  13556.     "Answer my yellow-button menu given the current selection and possibly some other view or controller state. The goal is to present in the menu only those possibilities which are legal commands at this juncture. If debugging is true, present a additional options which might be useful to implementors and other gurus."
  13557.  
  13558.     | argCount |
  13559.     argCount _ model selected size.
  13560.  
  13561.     "add superclass menu items"
  13562.     super addMenuItems: debugging.
  13563.  
  13564.     (lastInserted notNil) ifTrue:
  13565.         [myMenu add: ' another ' action: #another.
  13566.          myMenu addLine].
  13567.  
  13568.     (argCount > 0) ifTrue:
  13569.         [(argCount > 1) ifTrue:
  13570.             [myMenu add: ' merge ' action: #merge].
  13571.          myMenu add: ' unmerge ' action: #unmerge.
  13572.          myMenu add: ' delete ' action: #delete.
  13573.          myMenu add: ' extract ' action: #extract.
  13574.          myMenu addLine].
  13575.  
  13576.     (argCount = 2) ifTrue:
  13577.         [myMenu add: ' h-align ' action: #hAlign.
  13578.          myMenu add: ' v-align ' action: #vAlign.
  13579.          myMenu addLine].
  13580.  
  13581.     (model thing isUseView)
  13582.         ifTrue: [myMenu add: ' view source ' action: #viewSource]
  13583.         ifFalse:
  13584.             [myMenu add: ' make module ' action: #defineModule.
  13585.              (model thing class useView notNil)
  13586.                 ifTrue: [myMenu add: ' view module ' action: #viewModule]].!
  13587.  
  13588. another
  13589.     "Insert another part like the most recently inserted part."
  13590.  
  13591.      (model thing isStructureModifiable not | lastInserted isNil)
  13592.         ifTrue: [self flash]
  13593.         ifFalse: [self insertThing: lastInserted].!
  13594.  
  13595. defineModule
  13596.  
  13597.     | topView moduleView |
  13598.     topView _ view topView.
  13599.     topView removeSubViews.
  13600.     moduleView _
  13601.         (ThingModuleView new)
  13602.             model: (ThingAdaptor on: model thing).
  13603.     moduleView constructorView: view.
  13604.     topView addSubView: moduleView.
  13605.     moduleView scrollOffset: view scrollOffset.
  13606.     topView displaySubViews.
  13607.     self done: true.    "relinquish control"!
  13608.  
  13609. delete
  13610.     "Delete the selected parts."
  13611.  
  13612.     | proto partNames |
  13613.     proto _ model thing.
  13614.     (proto isStructureModifiable)
  13615.         ifFalse: [^view flash].    "can't modify this thing"
  13616.  
  13617.     partNames _ model selected asSet collect:
  13618.         [: part | (part allTopParentPaths first) first].
  13619.     partNames do:
  13620.         [: partName | proto removePartNamed: partName].
  13621.     model updateCaches.
  13622.     Cursor normal show.
  13623.     view displayView.!
  13624.  
  13625. extract
  13626.     "Extract the selected parts from all merges in which they participate."
  13627.  
  13628.     | proto |
  13629.     proto _ model thing.
  13630.     (proto isStructureModifiable)
  13631.         ifFalse: [^view flash].    "can't modify this thing"
  13632.  
  13633.     model selected asSet do:
  13634.         [: part |
  13635.          proto extractPart: part referenceToYourself].
  13636.  
  13637.     model updateCaches.
  13638.     Cursor normal show.
  13639.     view displayView.!
  13640.  
  13641. hAlign
  13642.     "Horizontally align (with an offset) the two selected parts."
  13643.  
  13644.     | args offset top bottom |
  13645.     args _ model selected asOrderedCollection.
  13646.     (args size = 2) ifFalse: [view flash. ^self].
  13647.  
  13648.     offset _ 0.
  13649.     (Sensor leftShiftDown) ifTrue:
  13650.         [offset _
  13651.             FillInTheBlank request: 'Vertical offset (in pixels)?' initialAnswer: '0'.
  13652.          (offset isEmpty)
  13653.             ifTrue: [offset _ 0]
  13654.             ifFalse: [offset _ (Number readFrom: offset readStream) rounded abs]].
  13655.  
  13656.     (args first location y < args last location y)
  13657.         ifTrue: [top _ args first. bottom _ args last]
  13658.         ifFalse: [top _ args last. bottom _ args first].
  13659.  
  13660.     model thing addConstraint:
  13661.         (OffsetConstraint
  13662.             ref: (top location->#y) copyFromTopParent
  13663.             ref: (bottom location->#y) copyFromTopParent
  13664.             strength: #strongPreferred
  13665.             offset: offset).
  13666.  
  13667.     model updateCaches.
  13668.     view displayView.!
  13669.  
  13670. merge
  13671.     "Merge the currently selected parts."
  13672.  
  13673.     | parts |
  13674.     parts _ model selected asOrderedCollection.
  13675.     (((parts size > 1) & (model thing isStructureModifiable)) and:
  13676.       [self canMergeParts: parts])
  13677.         ifFalse: [view flash. ^self].
  13678.     (self mergeParts: parts)
  13679.         ifTrue: [view newLabel: model name].
  13680.     view displayView.!
  13681.  
  13682. unmerge
  13683.     "Completely unmerge each of the currently selected parts This will do nothing to the parts that were not merges."
  13684.  
  13685.     | parts |
  13686.     (model thing isStructureModifiable)
  13687.         ifFalse: [view flash. ^self].    
  13688.     parts _ model selected asOrderedCollection
  13689.         collect: [: p | p referenceToYourself].
  13690.     (self unmergeParts: parts)
  13691.         ifTrue: [view newLabel: model name].
  13692.     view displayView.!
  13693.  
  13694. vAlign
  13695.     "Vertically align (with an offset) the two selected parts."
  13696.  
  13697.     | args offset left right |
  13698.     args _ model selected asOrderedCollection.
  13699.     (args size = 2) ifFalse: [view flash. ^self].
  13700.  
  13701.     offset _ 0.
  13702.     (Sensor leftShiftDown) ifTrue:
  13703.         [offset _
  13704.             FillInTheBlank request: 'Horizonal offset (in pixels)?' initialAnswer: '0'.
  13705.          (offset isEmpty)
  13706.             ifTrue: [offset _ 0]
  13707.             ifFalse: [offset _ (Number readFrom: offset readStream) rounded abs]].
  13708.  
  13709.     (args first location x < args last location x)
  13710.         ifTrue: [left _ args first. right _ args last]
  13711.         ifFalse: [left _ args last. right _ args first].
  13712.  
  13713.     model thing addConstraint:
  13714.         (OffsetConstraint
  13715.             ref: (left location->#x) copyFromTopParent
  13716.             ref: (right location->#x) copyFromTopParent
  13717.             strength: #strongPreferred
  13718.             offset: offset).
  13719.  
  13720.     model updateCaches.
  13721.     view displayView.!
  13722.  
  13723. viewModule
  13724.     "Change my model to the use view for my model."
  13725.  
  13726.     (model thing class useView isNil)
  13727.         ifTrue: [^view flash].
  13728.     self viewThing: (model thing class useView prototype).!
  13729.  
  13730. viewSource
  13731.     "Change my model to the construction view for my model, which should be a ModuleThing."
  13732.  
  13733.     (model thing class constructionView isNil)
  13734.         ifTrue: [^view flash].
  13735.     self viewThing: (model thing class constructionView prototype).!
  13736.  
  13737. viewThing: aThing
  13738.     "Change my model to the given Thing."
  13739.  
  13740.     view model thing: aThing.
  13741.     view newLabel: model name.
  13742.     view displayView.! !
  13743.  
  13744. !ThingConstructorController methodsFor: 'direct manipulation'!
  13745.  
  13746. displayWithMergeFeedbackFor: aThing
  13747.     "Test whether I could merge the given part with the part 'under' it. If so, highlight the part. If not, do the normal display-while-moving."
  13748.  
  13749.     | proto thingLocation otherThing tempForm |
  13750.     proto _ model thing.
  13751.     (proto isStructureModifiable)
  13752.         ifFalse: [^view displayFeedback].
  13753.     thingLocation _ aThing location asPoint.
  13754.     otherThing _ (model selectableGlyphs)
  13755.         detect: [: g |
  13756.             ((g ~= aThing) & (g containsPoint: thingLocation)) and:
  13757.             [proto canMerge: aThing with: g]]
  13758.         ifNone: [nil].
  13759.  
  13760.     (otherThing isNil)
  13761.         ifTrue: [view displayFeedback]
  13762.         ifFalse:
  13763.             ["highlight the Thing we could merge with"
  13764.              view
  13765.                 displayFeedbackWithBox:
  13766.                     ((otherThing boundingBox)
  13767.                         insetOriginBy: -6 cornerBy: -6)
  13768.                 width: 2]!
  13769.  
  13770. moveAt: aPoint
  13771.     "Move all selected parts. If only one part is being moved, try to merge it with the part (if any) at its new location."
  13772.  
  13773.     | parts partLocations |
  13774.     parts _ model selected asOrderedCollection.
  13775.     (parts size == 1)
  13776.         ifTrue:    "do a merge"
  13777.             [self
  13778.                 while: [sensor anyButtonPressed]
  13779.                 merge: parts first
  13780.                 refPoint: aPoint]
  13781.         ifFalse:    "do a group-move"
  13782.             [partLocations _ parts collect: [: p | p location].
  13783.              self
  13784.                 while: [sensor anyButtonPressed]
  13785.                 move: partLocations
  13786.                 refPoint: aPoint].
  13787.     view computeEnclosingRectangle.
  13788.     view displayView.!
  13789.  
  13790. while: testBlock merge: aThing refPoint: refPoint
  13791.     "Move the given Thing. Give feedback on the possibility of merging with any Thing under the cursor. Do the merge if the mouse is released at such a moment."
  13792.  
  13793.     | point oldPoint |
  13794.     self
  13795.         addMouseConstraintsFor: (Array with: aThing location)
  13796.         with: (Array with: aThing location asPoint - refPoint).
  13797.     [testBlock value] whileTrue:
  13798.         [point _ sensor cursorPoint.
  13799.          (oldPoint ~= sensor cursorPoint) ifTrue:
  13800.             [running ifTrue: [model advanceHistory].
  13801.              plan execute.
  13802.              self displayWithMergeFeedbackFor: aThing]].
  13803.     self removeMouseConstraints.
  13804.     self tryToMerge: aThing.! !
  13805.  
  13806. !ThingConstructorController methodsFor: 'part insertion'!
  13807.  
  13808. insertThing: protoType
  13809.     "Insert the given Thing as a new part of my model and allow the user to place it."
  13810.  
  13811.     | newPart |
  13812.     lastInserted _ protoType.
  13813.     lastMenuItem _ #another.
  13814.     newPart _ protoType clone.
  13815.     (model thing addThing: newPart)
  13816.         ifTrue: [view newLabel: model name].
  13817.     model updateCaches.
  13818.     self placeWhole: newPart.!
  13819.  
  13820. placeWhole: aPart
  13821.     "Position the given part as a whole, including all moveable sub-parts. The moveable sub-parts will follow the cursor until a mouse button is pressed."
  13822.  
  13823.     | partLocations center |
  13824.     partLocations _
  13825.         (aPart selectableGlyphs asOrderedCollection)
  13826.             collect: [: p | p location].
  13827.     (partLocations isEmpty) ifTrue: [^self].
  13828.     center _
  13829.         (partLocations
  13830.             inject: (partLocations first asPoint extent: 0@0)
  13831.             into:
  13832.                 [: rect : location |
  13833.                  rect merge: (location asPoint extent: 0@0)]) center.
  13834.     self
  13835.         while: [sensor anyButtonPressed not]
  13836.         move: partLocations
  13837.         refPoint: view insetDisplayBox topLeft + center.
  13838.     sensor waitNoButton.! !
  13839.  
  13840. !ThingConstructorController methodsFor: 'merging/unmerging'!
  13841.  
  13842. canMergeParts: partsList
  13843.     "Answer true if the given parts can all be merged together. I assume that the given list contains at least two parts."
  13844.  
  13845.     | proto part1 |
  13846.     proto _ model thing.
  13847.     (proto isStructureModifiable) ifFalse: [^false].
  13848.     part1 _ partsList first.
  13849.     (partsList copyFrom: 2 to: partsList size) do:
  13850.         [: partN | (proto canMerge: partN with: part1) ifFalse: [^false]].
  13851.     ^true!
  13852.  
  13853. copyValueFrom: part1 to: part2
  13854.     "If part1 is a Node Thing, fix part2's value part before doing a merge. However, do not do this if part2's value is determined by a constraint. Finally, any value has precedence over a value of nil. Assume that part1 and part2 are Things of the same class."
  13855.  
  13856.     "ignore non-Node Things"
  13857.     (part1 isMemberOf: Node) ifFalse: [^self].
  13858.  
  13859.     "exterminate nil's, if there are any"
  13860.     (part1 value isNil) ifTrue:
  13861.         [part1 primvalue: part2 value].
  13862.     (part2 value isNil) ifTrue:
  13863.         [part2 primvalue: part1 value].
  13864.  
  13865.     "copy the value from part1 to the value slot of part2 unless part2 has constraints"
  13866.     part1 primvalue: part2 value.
  13867.     (part2 thingDataForYourself isNil) ifTrue:
  13868.         [part2 primvalue: part1 value].!
  13869.  
  13870. mergeParts: partsList
  13871.     "Merge the given parts. I assume that the sender has already determined that the parts can be merged. Answer true if my name had to be changed to perform the merge."
  13872.  
  13873.     | cluster nameChanged |
  13874.     cluster _ partsList first.
  13875.     nameChanged _ false.
  13876.     (partsList copyFrom: 2 to: partsList size) do:
  13877.         [: p |
  13878.          self copyValueFrom: cluster to: p.
  13879.          (model thing mergePart: p withPart: cluster) ifTrue:
  13880.             [nameChanged _ true]].
  13881.  
  13882.     " refresh the glyphs cache and reselect the merged part"
  13883.     model updateCaches.
  13884.     partsList do:
  13885.         [: p | (p parents notNil) ifTrue: [model select: p]].
  13886.  
  13887.     ^nameChanged!
  13888.  
  13889. tryToMerge: p1
  13890.     "Attempt to merge the given part with the part 'under' it. This is done at the end of a move operation if only one part was being moved and allows the user to perform a merge by simply stacking two mergeable parts."
  13891.  
  13892.     | p1Location p2 |
  13893.     p1Location _ p1 location asPoint.
  13894.     p2 _ (model selectableGlyphs)
  13895.         detect: [: g |
  13896.             ((g ~~ p1) & (g containsPoint: p1Location)) and:
  13897.               [self canMergeParts: (Array
  13898.                     with: p1
  13899.                     with: g)]]
  13900.         ifNone: [^self].
  13901.     (self mergeParts: (Array with: p1 with: p2))
  13902.         ifTrue: [view newLabel: model name].
  13903.     model updateCaches.
  13904.     view displayView.!
  13905.  
  13906. unmergeCluster: aPart
  13907.     "Completely unmerge the given part (i.e. if three points were merged to create the part, it will be replaced by three new points. Collect references for all the selectable newly liberated parts into the given set. Answer true if my Thing changed its name."
  13908.  
  13909.     | root paths delta nameChanged |
  13910.     root _ aPart value topParent.
  13911.     paths _ (aPart value allTopParentPaths)
  13912.                 collect: [: path | Reference on: root path: path].
  13913.     (paths size < 2)
  13914.         ifTrue: [^false].    "nothing to unmerge"
  13915.  
  13916.     delta _ 5.
  13917.     nameChanged _ false.
  13918.     (paths copyFrom: 1 to: paths size - 1) do:
  13919.         [: ref |
  13920.          (model thing extractMergedPart: ref) ifTrue:
  13921.             [nameChanged _ true].
  13922.          "hack to offset locations to make unmerge visible"
  13923.          (ref value selectableGlyphs) do:
  13924.             [: g | (g location) set: #x to: (g location asPoint x + delta)].
  13925.          delta _ delta + 5].
  13926.  
  13927.     "make anchor nodes revert to nil value"
  13928.     paths do:
  13929.         [: ref |
  13930.          (ref finalVariable isMemberOf: NodeAnchor)
  13931.             ifTrue: [(ref, #(value)) value: nil]].
  13932.  
  13933.     model updateCaches.
  13934.     paths do:
  13935.         [: ref |
  13936.             (ref value selectableGlyphs) do:
  13937.                 [: glyph | model select: glyph]].
  13938.     ^nameChanged!
  13939.  
  13940. unmergeParts: partsList
  13941.     "Unmerge the parts with the given references and answer true if my name had to be changed to perform the operation. I assume the sender has verified that the model's structure can be modified."
  13942.  
  13943.     | changed |
  13944.     changed _ false.
  13945.     partsList do:
  13946.         [: part |
  13947.          (self unmergeCluster: part) ifTrue: [changed _ true]].
  13948.     ^changed! !
  13949.  
  13950. LayoutGlyph subclass: #ConstraintGlyph
  13951.     instanceVariableNames: 'name nameForm showLabel inVars outVars unusedVars '
  13952.     classVariableNames: ''
  13953.     poolDictionaries: ''
  13954.     category: 'ThingLabII-UI-Debugger'!
  13955.  
  13956.  
  13957. !ConstraintGlyph methodsFor: 'initialize-release'!
  13958.  
  13959. initialize
  13960.     "Use a dummy Form until nameForm can be updated from the actual object name."
  13961.  
  13962.     super initialize.
  13963.     self name: 'R'.
  13964.     showLabel _ true.
  13965.     inVars _ outVars _ unusedVars _ #().! !
  13966.  
  13967. !ConstraintGlyph methodsFor: 'accessing'!
  13968.  
  13969. allVarGlyphs
  13970.     "Answer the collection of all VariableGlyphs associated with this constraint."
  13971.  
  13972.     ^inVars, outVars, unusedVars!
  13973.  
  13974. ins: ins outs: outs unused: unuseds
  13975.     "Tell me about the VariableGlyphs for my input, output, and unused variables."
  13976.  
  13977.     inVars _ ins.
  13978.     outVars _ outs.
  13979.     unusedVars _ unuseds.!
  13980.  
  13981. name
  13982.     "Answer my name."
  13983.  
  13984.     ^name!
  13985.  
  13986. name: aString
  13987.     "Set my name and update my nameForm cache."
  13988.  
  13989.     name _ aString.
  13990.     nameForm _
  13991.         (Paragraph
  13992.             withText: self name asText
  13993.             style: ((TextStyle default) lineGrid: 12; baseline: 9)) centered asForm.
  13994.     nameForm offset: (nameForm computeBoundingBox extent // -2).! !
  13995.  
  13996. !ConstraintGlyph methodsFor: 'show/hide label'!
  13997.  
  13998. hideLabel
  13999.     "Hide my label."
  14000.  
  14001.     showLabel _ false.!
  14002.  
  14003. labelIsHidden
  14004.     "Answer true if my label is currently hidden."
  14005.  
  14006.     ^showLabel not!
  14007.  
  14008. showLabel
  14009.     "Show my label."
  14010.  
  14011.     showLabel _ true.! !
  14012.  
  14013. !ConstraintGlyph methodsFor: 'glyph protocol'!
  14014.  
  14015. boundingBox
  14016.     "Answer my bounding box."
  14017.  
  14018.     ^nameForm computeBoundingBox translateBy: (location + nameForm offset)!
  14019.  
  14020. displayConnectionsOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox
  14021.     "Draw the connections to my variables."
  14022.  
  14023.     | line  p |
  14024.     line _ (Line new) form: (Form extent: 1@1) black.
  14025.     line beginPoint: location.
  14026.     "draw black lines to used variables"
  14027.     inVars, outVars do:
  14028.         [: varGlyph |
  14029.          line endPoint: (varGlyph connectArrowFrom: location).
  14030.          line
  14031.             displayOn: aDisplayMedium
  14032.             at: aDisplayPoint
  14033.             clippingBox: clipBox
  14034.             rule: Form over
  14035.             mask: Form black].
  14036.     "draw gray lines to unused variables"
  14037.     unusedVars do:
  14038.         [: varGlyph |
  14039.          line endPoint: (varGlyph connectArrowFrom: location).
  14040.          line
  14041.             displayOn: aDisplayMedium
  14042.             at: aDisplayPoint
  14043.             clippingBox: clipBox
  14044.             rule: Form over
  14045.             mask: Form gray].
  14046.     "draw arrow heads to output variables"
  14047.     outVars do:
  14048.         [: varGlyph |
  14049.          p _ varGlyph connectArrowFrom: location.
  14050.          (ArrowHead at: p vector: (varGlyph location - location))
  14051.             displayOn: aDisplayMedium
  14052.             at: aDisplayPoint
  14053.             clippingBox: clipBox].!
  14054.  
  14055. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox
  14056.  
  14057.     self
  14058.         displayConnectionsOn: aDisplayMedium
  14059.         at: aDisplayPoint
  14060.         clippingBox: clipBox.
  14061.  
  14062.     showLabel ifTrue:
  14063.         [nameForm
  14064.             displayOn: aDisplayMedium
  14065.             at: location + aDisplayPoint
  14066.             clippingBox: clipBox
  14067.             rule: (Form over)
  14068.             mask: (Form black)].!
  14069.  
  14070. highlightOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox
  14071.  
  14072.     showLabel ifTrue:
  14073.         [nameForm
  14074.             displayOn: aDisplayMedium
  14075.             at: location + aDisplayPoint
  14076.             clippingBox: clipBox
  14077.             rule: 12    "reversed"
  14078.             mask: (Form black)].! !
  14079. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  14080.  
  14081. ConstraintGlyph class
  14082.     instanceVariableNames: ''!
  14083.  
  14084.  
  14085. !ConstraintGlyph class methodsFor: 'instance creation'!
  14086.  
  14087. named: labelString
  14088.     "Answer a new instance with the given name."
  14089.  
  14090.     ^(self new) name: labelString! !
  14091.  
  14092. Scene subclass: #PartsBin
  14093.     instanceVariableNames: 'name icon allPartsFlag '
  14094.     classVariableNames: 'DefaultIcon GridX GridY TopBin '
  14095.     poolDictionaries: ''
  14096.     category: 'ThingLabII-UI-Parts Bin'!
  14097. PartsBin comment:
  14098. 'I contain a collection of Things and PartsBins, which are stored in PartsHolder objects in my glyphs collection. Like Things, I have a name and and icon, allowing me to be contained in other PartBins. If references to me appear in several parts bins, they will all display with the same name, icon, and parts selection. Some of my instances may be ''AllParts'' bins. An ''AllParts'' bin contains every currently existing Thing prototype.'!
  14099.  
  14100.  
  14101. !PartsBin methodsFor: 'initialize-release'!
  14102.  
  14103. initialize: nameString isAllParts: isAllParts
  14104.  
  14105.     super initialize.
  14106.     name _ nameString.
  14107.     icon _ DefaultIcon deepCopy.
  14108.     allPartsFlag _ isAllParts.
  14109.     allPartsFlag
  14110.         ifTrue: [self syncWithReality: nil].! !
  14111.  
  14112. !PartsBin methodsFor: 'accessing'!
  14113.  
  14114. allPartsFlag: aBoolean
  14115.  
  14116.     allPartsFlag _ aBoolean.!
  14117.  
  14118. icon
  14119.  
  14120.     ^icon!
  14121.  
  14122. icon: aForm
  14123.  
  14124.     icon _ aForm.!
  14125.  
  14126. isAllParts
  14127.  
  14128.     ^allPartsFlag!
  14129.  
  14130. name
  14131.  
  14132.     ^name!
  14133.  
  14134. name: aString
  14135.  
  14136.     name _ aString.! !
  14137.  
  14138. !PartsBin methodsFor: 'operations'!
  14139.  
  14140. addPart: aPartHolder
  14141.     "Note: You can't anything to All Parts."
  14142.  
  14143.     (self isAllParts) ifTrue: [^self].    "can't add to AllParts"
  14144.     self findLocationFor: aPartHolder.
  14145.     self addGlyph: aPartHolder.!
  14146.  
  14147. addPart: aPartHolder at: aLocation
  14148.     "Note: You can't add Things or bins to All Parts."
  14149.  
  14150.     (self isAllParts) ifTrue: [^self].
  14151.     self addGlyph: ((aPartHolder copy) location: aLocation).! !
  14152.  
  14153. !PartsBin methodsFor: 'part placement'!
  14154.  
  14155. aligned: aPartHolder
  14156.     "Answer true if aPartHolder is aligned with a gridpoint."
  14157.  
  14158.     ^((aPartHolder location x \\ GridX) = 0) and:
  14159.       [(aPartHolder location y \\ GridY) = 0]!
  14160.  
  14161. arrangeIn: box
  14162.     "Arrange all the parts so that they are aligned, non-overlapping, and as many as possible are inside the given box."
  14163.  
  14164.     | sortedGlyphs insideGlyphs outsideGlyphs l1 l2 |
  14165.     sortedGlyphs _ glyphs asSortedCollection:
  14166.         [: g1 : g2 |
  14167.          ((selected includes: g2) and: [(selected includes: g1) not]) or:
  14168.          [l1 _ g1 location. l2 _ g2 location.
  14169.          (l1 x abs + l1 y abs) < (l2 x abs + l2 y abs)]].
  14170.     insideGlyphs _ OrderedCollection new: glyphs size.
  14171.     outsideGlyphs _ OrderedCollection new: glyphs size.
  14172.     sortedGlyphs do:
  14173.         [: g |
  14174.          (self part: g inside: box)
  14175.             ifTrue: [insideGlyphs addLast: g]
  14176.             ifFalse: [outsideGlyphs addLast: g]].
  14177.  
  14178.     "tempoarily remove all parts so we can consider overlaps only with parts that have already been positioned; parts will be re-instated as they are positioned."
  14179.     glyphs _ glyphs species new: glyphs size.
  14180.     "move mis-aligned or overlapping parts within the view box"
  14181.     insideGlyphs do:
  14182.         [: g |
  14183.          BusyCursor inc.
  14184.          ((self aligned: g) not or: [self isOverlapping: g])
  14185.             ifTrue: [self findLocationFor: g inside: box].
  14186.           glyphs addLast: g].
  14187.  
  14188.     "try to move parts into the view box"
  14189.     outsideGlyphs do:
  14190.         [: g |
  14191.          BusyCursor inc.
  14192.          g location: box origin.        "start at the top left"
  14193.          self findLocationFor: g inside: box.
  14194.          glyphs addLast: g].!
  14195.  
  14196. findLocationFor: aPartHolder
  14197.     "Use when there may not be an open view for this PartsBin. Finds a location for aPartHolder assuming typical view dimensions. The location of aPartHolder is modified."
  14198.  
  14199.     self
  14200.         findLocationFor: aPartHolder
  14201.         inside: (0@0 corner: 200@120).!
  14202.  
  14203. findLocationFor: aPartHolder inside: box
  14204.     "Find a location in this bin for the given PartHolder and move it to that location. Try to stay inside the given bounding box."
  14205.  
  14206.     | possibleX possibleY rightEdge |
  14207.     possibleX _ (aPartHolder location x asFloat roundTo: GridX) max: GridX.
  14208.     possibleY _ (aPartHolder location y asFloat roundTo: GridY) max: GridY.
  14209.     rightEdge _ box width - (aPartHolder boundingBox width // 2) - 5.
  14210.     [true]
  14211.         whileTrue:
  14212.             [(possibleX > rightEdge) ifTrue:
  14213.                 [possibleX _ GridX.
  14214.                  possibleY _ possibleY + GridY].
  14215.              aPartHolder location: possibleX@possibleY.
  14216.              (self isOverlapping: aPartHolder)
  14217.                 ifFalse: [^self].
  14218.              possibleX _ possibleX + GridX].!
  14219.  
  14220. isOverlapping: aPartHolder
  14221.     "Answer true if aPartHolder is overlaps some other PartHolder in this bin."
  14222.     "Note: Because computing the intersection of bounding boxes proved very expensive, this algorithm simply checks to see if aPartHolder is within a small Euclidian distance of any other PartHolder in this parts bin."
  14223.  
  14224.     | vec |
  14225.     glyphs do:
  14226.         [: g |
  14227.          vec _ g location - aPartHolder location.
  14228.          ((g ~~ aPartHolder) and:
  14229.           [(vec x abs + vec y abs) < 10])
  14230.             ifTrue: [^true]].
  14231.     ^false!
  14232.  
  14233. part: aPartHolder inside: aRectangle
  14234.     "Answer true if aPartHolder is completely inside the given rectangle."
  14235.  
  14236.     ^aRectangle contains: aPartHolder boundingBox! !
  14237.  
  14238. !PartsBin methodsFor: 'updating'!
  14239.  
  14240. syncWithReality: viewBox
  14241.     "Update myself from the underlying Thing database. If viewBox is not nil, then it is the window of the view on me that initiated this operation."
  14242.  
  14243.     | realThings oldThings pHolder changed |
  14244.     changed _ false.
  14245.     BusyCursor begin.
  14246.  
  14247.     "Construct a list of all Things that currently exist."
  14248.     realThings _ IdentitySet new.
  14249.     ((SystemOrganization
  14250.         listAtCategoryNamed: 'Things-Built' asSymbol),
  14251.     (SystemOrganization
  14252.         listAtCategoryNamed: 'Things-Primitive' asSymbol)) do:
  14253.             [: sym |
  14254.              realThings add: (Smalltalk at: sym) prototype.
  14255.              BusyCursor inc].
  14256.  
  14257.     "Remove from this parts bin any Things that no longer exist."
  14258.     (glyphs copy) do: [: g |
  14259.         ((g holdsThing) and: [(realThings includes: g cargo) not]) ifTrue:
  14260.             ["remove an obsolete thing"
  14261.              changed _ true.
  14262.              self removeGlyph: g].
  14263.         BusyCursor inc].
  14264.  
  14265.     "If I am AllParts, add to myself any new Things."
  14266.     (self isAllParts) ifTrue:
  14267.         [oldThings _ self thingsSet.
  14268.          (realThings asOrderedCollection) do:
  14269.             [: thing |
  14270.              (oldThings includes: thing) ifFalse:
  14271.                 [pHolder _ PartHolder on: thing.
  14272.                  changed _ true.
  14273.                  (viewBox notNil)
  14274.                      ifTrue: [self findLocationFor: pHolder inside: viewBox]
  14275.                      ifFalse: [self findLocationFor: pHolder].
  14276.                  self addGlyph: pHolder.
  14277.                  BusyCursor inc]]].
  14278.  
  14279.     "Update all name forms."
  14280.     glyphs do: [: g | g updateNameForm].
  14281.     BusyCursor end.
  14282.     ^changed! !
  14283.  
  14284. !PartsBin methodsFor: 'private'!
  14285.  
  14286. partsBinsSet
  14287.     "Answer a set of all the PartsBins I contain."
  14288.  
  14289.     | bins |
  14290.     bins _ IdentitySet new: 200.
  14291.     glyphs do:
  14292.         [: partHolder |
  14293.          (partHolder holdsPartsBin)
  14294.             ifTrue: [bins add: partHolder cargo]].
  14295.     ^bins!
  14296.  
  14297. thingsSet
  14298.     "Answer a set of all the Things I contain."
  14299.  
  14300.     | things |
  14301.     things _ IdentitySet new: 200.
  14302.     glyphs do:
  14303.         [: partHolder |
  14304.          (partHolder holdsThing)
  14305.             ifTrue: [things add: partHolder cargo]].
  14306.     ^things! !
  14307. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  14308.  
  14309. PartsBin class
  14310.     instanceVariableNames: ''!
  14311.  
  14312.  
  14313. !PartsBin class methodsFor: 'instance creation'!
  14314.  
  14315. newAllParts
  14316.     "Answer a parts bin that contains all currently existing Things."
  14317.  
  14318.     ^(super new)
  14319.         initialize: 'All Parts'
  14320.         isAllParts: true!
  14321.  
  14322. newNamed: aString
  14323.     "Answer a new, empty bin with the given name."
  14324.  
  14325.     ^(super new)
  14326.         initialize: aString
  14327.         isAllParts: false! !
  14328.  
  14329. !PartsBin class methodsFor: 'top bin access'!
  14330.  
  14331. newTopBin
  14332.     "Ask for confirmation, then create the root of the bin tree from scratch. Note that this will throw away all user-created bins!! All Things will still be accessible via the All Parts bin, of course."
  14333.     "PartsBin newTopBin."
  14334.  
  14335.     (self confirm:
  14336. 'Making a new Top Bin will remove all
  14337. user bins. Do you wish to continue?')
  14338.         ifFalse: [^nil].
  14339.  
  14340.     TopBin _ self newNamed: 'Top Bin'.
  14341.     TopBin
  14342.         addPart: (PartHolder on: (PartsBin newAllParts))
  14343.         at: GridX@GridY.!
  14344.  
  14345. topBin
  14346.     "Answer the root of the bin tree."
  14347.  
  14348.     ^TopBin!
  14349.  
  14350. updateAllBins
  14351.     "Update all PartsBins accessible from the top bin. Used after updating all the PrimitiveThings prototypes."
  14352.     "PartsBin updateAllBins"
  14353.  
  14354.     | toDo partsBin |
  14355.     toDo _ OrderedCollection with: TopBin.
  14356.     [toDo isEmpty] whileFalse:
  14357.         [partsBin _ toDo removeFirst.
  14358.          toDo addAll: partsBin partsBinsSet.
  14359.          partsBin syncWithReality: nil].! !
  14360.  
  14361. !PartsBin class methodsFor: 'grid parameters'!
  14362.  
  14363. gridX
  14364.  
  14365.     ^GridX!
  14366.  
  14367. gridX: aNumber
  14368.  
  14369.     GridX _ aNumber.!
  14370.  
  14371. gridY
  14372.  
  14373.     ^GridY!
  14374.  
  14375. gridY: aNumber
  14376.  
  14377.     GridY _ aNumber.! !
  14378.  
  14379. !PartsBin class methodsFor: 'class initialization'!
  14380.  
  14381. initialize
  14382.     "Initialize the default PartsBin icon and the grid for parts placement."
  14383.     "PartsBin initialize."
  14384.  
  14385.     DefaultIcon _ Form
  14386.         extent: 16@16
  14387.         fromArray: #(16383 16387 32773 65533 32773 36901 32773 65533 32773 36901 32773 65533 32773 36901 32774 65532)
  14388.         offset: 0@0.
  14389.     GridX _ 60.
  14390.     GridY _ 35.
  14391.  
  14392.     "make a new TopBin"
  14393.     TopBin _ self newNamed: 'Top Bin'.
  14394.     TopBin
  14395.         addPart: (PartHolder on: (PartsBin newAllParts))
  14396.         at: GridX@GridY.! !
  14397.  
  14398.  
  14399. Scene subclass: #MultiThingAdaptor
  14400.     instanceVariableNames: 'visibleGlyphs selectableGlyphs inputGlyphs thingDatas historyNodes '
  14401.     classVariableNames: ''
  14402.     poolDictionaries: ''
  14403.     category: 'ThingLabII-UI-Thing Views'!
  14404.  
  14405.  
  14406. !MultiThingAdaptor methodsFor: 'initialize-release'!
  14407.  
  14408. release
  14409.  
  14410.     super release.
  14411.     visibleGlyphs _ selectableGlyphs _ inputGlyphs _ nil.
  14412.     thingDatas _ historyNodes _ nil.! !
  14413.  
  14414. !MultiThingAdaptor methodsFor: 'access'!
  14415.  
  14416. name
  14417.     "Answer my name."
  14418.  
  14419.     ^'Thing Scene'!
  14420.  
  14421. thing
  14422.     "Answer my underlying Thing."
  14423.  
  14424.     self shouldNotImplement!
  14425.  
  14426. thing: aThing
  14427.     "Set my underlying Thing and update my caches accordingly."
  14428.  
  14429.     self shouldNotImplement!
  14430.  
  14431. thingDatas
  14432.     "Warning: thingDatasCache is a cache of my underlying Thing's ThingDatas. Care must be used to ensure that this cache is kept up to date. If in doubt, send me the message updateGlyphsCache."
  14433.  
  14434.     ^thingDatas! !
  14435.  
  14436. !MultiThingAdaptor methodsFor: 'glyphs access'!
  14437.  
  14438. inputGlyphs
  14439.     "Warning: inputGlyphs is a cache of my underlying Thing's input glyphs. Care must be used to ensure that this cache is kept up to date. If in doubt, send me the message updateGlyphsCache."
  14440.  
  14441.     ^inputGlyphs!
  14442.  
  14443. selectableGlyphs
  14444.     "Warning: selectableGlyphs is a cache of my underlying Thing's selectable glyphs. Care must be used to ensure that this cache is kept up to date. If in doubt, send me the message updateGlyphsCache."
  14445.  
  14446.     ^selectableGlyphs!
  14447.  
  14448. visibleGlyphs
  14449.     "Warning: glyphs is a cache of my underlying Thing's glyphs. Care must be used to ensure that this cache is kept up to date. If in doubt, send me the message updateGlyphsCache."
  14450.  
  14451.     ^visibleGlyphs! !
  14452.  
  14453. !MultiThingAdaptor methodsFor: 'glyphs'!
  14454.  
  14455. addGlyph: aThing
  14456.  
  14457.     super addGlyph: aThing.
  14458.     self updateCaches.!
  14459.  
  14460. isChanging: aThingGlyph
  14461.     "Answer true if the give glyph is undergoing changes that could effect how it is displayed."
  14462.  
  14463.     aThingGlyph glyphDependsOn do:
  14464.         [: aThing |
  14465.          (self thingIsChanging: aThing) ifTrue:
  14466.             [^true]].        "must redisplay this glyph every time"
  14467.  
  14468.     "the glyph does not depend on any changing parts"
  14469.     ^false!
  14470.  
  14471. removeGlyph: aThing
  14472.  
  14473.     super removeGlyph: aThing.
  14474.     self updateCaches.!
  14475.  
  14476. thingIsChanging: aThing
  14477.     "Answer true if the given Thing has a constrained part whose stay flag is not true."
  14478.  
  14479.     "if the thing has no thingDatas, then it is fixed"
  14480.     (aThing thingDatas isEmpty) ifTrue: [^false].
  14481.  
  14482.     aThing thingDatas do:
  14483.         [: thingData |
  14484.          (thingData stay not) ifTrue: [^true]].    "thing is not fixed"
  14485.     ^false    "thing is fixed"! !
  14486.  
  14487. !MultiThingAdaptor methodsFor: 'operations'!
  14488.  
  14489. advanceHistory
  14490.     "Advance all my cached history variables."
  14491.  
  14492.     historyNodes do: [: node | node advanceHistory].!
  14493.  
  14494. updateCaches
  14495.     "Update all my caches."
  14496.  
  14497.     self clearSelection.    "clear selection"
  14498.     visibleGlyphs _ IdentitySet new.
  14499.     selectableGlyphs _ IdentitySet new.
  14500.     inputGlyphs _ IdentitySet new.
  14501.     thingDatas _ IdentitySet new.
  14502.     historyNodes _ IdentitySet new.
  14503.  
  14504.     glyphs do:
  14505.         [: aThing |
  14506.          aThing visibleGlyphsInto: visibleGlyphs.
  14507.          aThing selectableGlyphsInto: selectableGlyphs.
  14508.          aThing inputGlyphsInto: inputGlyphs.
  14509.          aThing allThingDatasInto: thingDatas.
  14510.          aThing allThingsDo:
  14511.             [: subThing |
  14512.              (subThing keepsHistory) ifTrue:
  14513.                 [historyNodes add: subThing]]].
  14514.  
  14515.     visibleGlyphs _ visibleGlyphs asOrderedCollection.
  14516.     selectableGlyphs _ selectableGlyphs asOrderedCollection.
  14517.     inputGlyphs _ inputGlyphs asOrderedCollection.
  14518.     thingDatas _ thingDatas asOrderedCollection.
  14519.     historyNodes _ historyNodes asOrderedCollection.! !
  14520.  
  14521. LayoutGlyph subclass: #VariableGlyph
  14522.     instanceVariableNames: 'name nameForm showLabel '
  14523.     classVariableNames: ''
  14524.     poolDictionaries: ''
  14525.     category: 'ThingLabII-UI-Debugger'!
  14526.  
  14527.  
  14528. !VariableGlyph methodsFor: 'initialize-release'!
  14529.  
  14530. initialize
  14531.     "Use a dummy Form until nameForm can be updated from the actual object name."
  14532.  
  14533.     super initialize.
  14534.     self name: '???'.
  14535.     showLabel _ true.! !
  14536.  
  14537. !VariableGlyph methodsFor: 'accessing'!
  14538.  
  14539. icon
  14540.  
  14541.     ^(Form
  14542.         extent: 13@13
  14543.         fromArray: #(8128 8224 16400 32776 32776 32776 32776 32776 32776 32776 16400 8224 8128)
  14544.         offset: -6@-6)!
  14545.  
  14546. name
  14547.     "Answer my name."
  14548.  
  14549.     ^name!
  14550.  
  14551. name: aString
  14552.     "Set my name and update my nameForm cache."
  14553.  
  14554.     name _ aString.
  14555.     nameForm _
  14556.         (Paragraph
  14557.             withText: self name asText
  14558.             style: ((TextStyle default) lineGrid: 12; baseline: 9)) centered asForm.
  14559.     nameForm offset: (nameForm computeBoundingBox extent // -2).! !
  14560.  
  14561. !VariableGlyph methodsFor: 'show/hide label'!
  14562.  
  14563. hideLabel
  14564.     "Hide my label."
  14565.  
  14566.     showLabel _ false.!
  14567.  
  14568. labelIsHidden
  14569.     "Answer true if my label is currently hidden."
  14570.  
  14571.     ^showLabel not!
  14572.  
  14573. showLabel
  14574.     "Show my label."
  14575.  
  14576.     showLabel _ true.! !
  14577.  
  14578. !VariableGlyph methodsFor: 'connections'!
  14579.  
  14580. angle: vector
  14581.     "Answer the approximate angle of the given vector."
  14582.  
  14583.     | slope absSlope angle |
  14584.     (vector x = 0) ifTrue:
  14585.         [(vector y >= 0)
  14586.             ifTrue: [^270]
  14587.             ifFalse: [^90]].
  14588.  
  14589.     slope _ vector y negated asFloat / vector x asFloat.
  14590.     absSlope _ slope abs.
  14591.     (absSlope < 0.5) ifTrue: [angle _ 0].
  14592.     ((absSlope >= 0.5) & (absSlope < 2.0)) ifTrue: [angle _ 45].
  14593.     (absSlope >= 2.0) ifTrue: [angle _ 90].
  14594.     (slope > 0)
  14595.         ifTrue:
  14596.             [(vector x > 0)
  14597.                 ifTrue: [^0 + angle]
  14598.                 ifFalse: [^180 + angle]]
  14599.         ifFalse:
  14600.             [(vector x < 0)
  14601.                 ifTrue: [^180 - angle]
  14602.                 ifFalse: [^360 - angle]].!
  14603.  
  14604. connectArrowFrom: aPoint
  14605.     "Answer the proper endpoint of a line with an arrow head pointing to me from the given point."
  14606.  
  14607.     | angle |
  14608.     angle _ self angle: (location - aPoint).
  14609.     (angle == 0) ifTrue: [^-12@0 + location].
  14610.     (angle == 45) ifTrue: [^-11@11 + location].
  14611.     (angle == 90) ifTrue: [^0@12 + location].
  14612.     (angle == 135) ifTrue: [^11@11 + location].
  14613.     (angle == 180) ifTrue: [^12@0 + location].
  14614.     (angle == 225) ifTrue: [^11@-11 + location].
  14615.     (angle == 270) ifTrue: [^0@-12 + location].
  14616.     (angle == 315) ifTrue: [^-11@-11 + location].
  14617.     (angle == 360) ifTrue: [^-12@0 + location].!
  14618.  
  14619. connectLineFrom: aPoint
  14620.     "Answer the proper endpoint of a line (sans arrow head) to me from the given point."
  14621.  
  14622.     | angle |
  14623.     angle _ self angle: (location - aPoint).
  14624.     (angle == 0) ifTrue: [^-6@0 + location].
  14625.     (angle == 45) ifTrue: [^-5@5 + location].
  14626.     (angle == 90) ifTrue: [^0@6 + location].
  14627.     (angle == 135) ifTrue: [^5@5 + location].
  14628.     (angle == 180) ifTrue: [^6@0 + location].
  14629.     (angle == 225) ifTrue: [^5@-5 + location].
  14630.     (angle == 270) ifTrue: [^0@-6 + location].
  14631.     (angle == 315) ifTrue: [^-5@-5 + location].
  14632.     (angle == 360) ifTrue: [^-6@0 + location].! !
  14633.  
  14634. !VariableGlyph methodsFor: 'glyph protocol'!
  14635.  
  14636. boundingBox
  14637.     "Answer my bounding box."
  14638.  
  14639.     | icon |
  14640.     icon _ self icon.
  14641.     ^((icon computeBoundingBox translateBy: icon offset) merge:
  14642.       (nameForm computeBoundingBox translateBy: nameForm offset + (0@15)))
  14643.         translateBy: location!
  14644.  
  14645. containsPoint: aPoint
  14646.     "Answer true if either my icon or name boxes contains the given point. Allow a little slop around the icon box."
  14647.  
  14648.     | iconBox labelBox |
  14649.     iconBox _ (self icon computeBoundingBox) translateBy: (location + self icon offset).
  14650.     ((iconBox expandBy: 2) containsPoint: aPoint) ifTrue:
  14651.         [^true].
  14652.  
  14653.     showLabel ifTrue:
  14654.         [labelBox _ (nameForm computeBoundingBox) translateBy:
  14655.                     (location + nameForm offset + (0@15)).
  14656.          (labelBox containsPoint: aPoint) ifTrue:
  14657.             [^true]].
  14658.     ^false!
  14659.  
  14660. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox
  14661.  
  14662.     self icon
  14663.         displayOn: aDisplayMedium
  14664.         at: location + aDisplayPoint
  14665.         clippingBox: clipBox
  14666.         rule: (Form under)
  14667.         mask: (Form black).
  14668.  
  14669.     showLabel ifTrue:
  14670.         [nameForm
  14671.             displayOn: aDisplayMedium
  14672.             at: location + aDisplayPoint + (0@15)
  14673.             clippingBox: clipBox
  14674.             rule: (Form over)
  14675.             mask: (Form black)].!
  14676.  
  14677. highlightOn: aDisplayMedium at: aDisplayPoint clippingBox: clipBox
  14678.  
  14679.     | icon iconBox |
  14680.     icon _ self icon.
  14681.     iconBox _ icon computeBoundingBox expandBy: 1.
  14682.     aDisplayMedium
  14683.         border: (iconBox translateBy: location + aDisplayPoint + icon offset)
  14684.         widthRectangle: (1@1 corner: 1@1)
  14685.         mask: (Form gray)
  14686.         clippingBox: clipBox.
  14687.  
  14688.     showLabel ifTrue:
  14689.         [nameForm
  14690.             displayOn: aDisplayMedium
  14691.             at: location + aDisplayPoint + (0@15)
  14692.             clippingBox: clipBox
  14693.             rule: 12    "reversed"
  14694.             mask: (Form black)].! !
  14695. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  14696.  
  14697. VariableGlyph class
  14698.     instanceVariableNames: ''!
  14699.  
  14700.  
  14701. !VariableGlyph class methodsFor: 'instance creation'!
  14702.  
  14703. named: aString at: aPoint
  14704.     "Answer a new instance with the given name and location."
  14705.  
  14706.     ^(super new)
  14707.         name: aString;
  14708.         location: aPoint! !
  14709.  
  14710. BasicThingController subclass: #MultiThingController
  14711.     instanceVariableNames: ''
  14712.     classVariableNames: ''
  14713.     poolDictionaries: ''
  14714.     category: 'ThingLabII-UI-Thing Views'!
  14715.  
  14716.  
  14717. !MultiThingController methodsFor: 'menu operations'!
  14718.  
  14719. explain
  14720.     "If a single part is selected, explain that part. Otherwise, explain the top-level Thing (the Thing under construction)."
  14721.  
  14722.     (self argument notNil)
  14723.         ifTrue: [Explanation openOn: self argument]
  14724.         ifFalse: [view flash].!
  14725.  
  14726. inspectThing
  14727.     "If a single part is selected, inspect that part. Otherwise, inspect the top-level Thing (the Thing under construction)."
  14728.  
  14729.     (self argument notNil)
  14730.         ifTrue: [self argument inspect]
  14731.         ifFalse: [    view flash].!
  14732.  
  14733. openDebugger
  14734.     "Open a ThingDebugView on my Thing."
  14735.  
  14736.     view flash.! !
  14737.  
  14738. IconGlyph subclass: #PartHolder
  14739.     instanceVariableNames: 'cargo lastFrame '
  14740.     classVariableNames: ''
  14741.     poolDictionaries: ''
  14742.     category: 'ThingLabII-UI-Parts Bin'!
  14743. PartHolder comment:
  14744. 'I am a holder for parts and parts bins. I inherit a location variable from Glyph and protocol for displaying myself from IconGlyph. I have a contents variable to store the Thing or PartsBin that I contain. My name and icon are those of my contents; I can only store objects that have names and icons.'!
  14745.  
  14746.  
  14747. !PartHolder methodsFor: 'initialize-release'!
  14748.  
  14749. initialize
  14750.  
  14751.     super initialize.
  14752.     cargo _ nil.
  14753.     lastFrame _ nil.! !
  14754.  
  14755. !PartHolder methodsFor: 'accessing'!
  14756.  
  14757. cargo
  14758.  
  14759.     ^cargo!
  14760.  
  14761. cargo: anObject
  14762.  
  14763.     cargo _ anObject.
  14764.     self updateNameForm.!
  14765.  
  14766. icon
  14767.  
  14768.     ^cargo icon!
  14769.  
  14770. icon: aForm
  14771.  
  14772.     cargo icon: aForm.!
  14773.  
  14774. lastFrame
  14775.     "Answer the view frame when this part was last closed."
  14776.  
  14777.     ^lastFrame!
  14778.  
  14779. lastFrame: aRectangle
  14780.     "Set the view frame when this part was last closed."
  14781.  
  14782.     lastFrame _ aRectangle.!
  14783.  
  14784. name
  14785.  
  14786.     ^cargo name!
  14787.  
  14788. name: aString
  14789.  
  14790.     cargo name: aString.
  14791.     self updateNameForm.! !
  14792.  
  14793. !PartHolder methodsFor: 'testing'!
  14794.  
  14795. holdsAllParts
  14796.     "Answer true if my cargo is an 'All Parts' PartsBin."
  14797.  
  14798.     ^(self cargo isMemberOf: PartsBin) and:
  14799.      [self cargo isAllParts]!
  14800.  
  14801. holdsPartsBin
  14802.     "Answer true if my cargo is a PartsBin."
  14803.  
  14804.     ^self cargo isMemberOf: PartsBin!
  14805.  
  14806. holdsThing
  14807.     "Answer true if my cargo is a Thing."
  14808.  
  14809.     ^self holdsPartsBin not! !
  14810. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  14811.  
  14812. PartHolder class
  14813.     instanceVariableNames: ''!
  14814.  
  14815.  
  14816. !PartHolder class methodsFor: 'instance creation'!
  14817.  
  14818. on: anObject
  14819.     "Answer a new PartHolder for the given object."
  14820.  
  14821.     ^(super new) cargo: anObject! !
  14822.  
  14823. SceneController subclass: #ThingDebugController
  14824.     instanceVariableNames: ''
  14825.     classVariableNames: ''
  14826.     poolDictionaries: ''
  14827.     category: 'ThingLabII-UI-Debugger'!
  14828.  
  14829.  
  14830. !ThingDebugController methodsFor: 'menu operations'!
  14831.  
  14832. addMenuItems: debugging
  14833.     "Answer my yellow-button menu given the current selection and possibly some other view or controller state. The goal is to present in the menu only those possibilities which are legal commands at this juncture. If debugging is true, present a additional options which might be useful to implementors and other gurus."
  14834.  
  14835.     super addMenuItems: debugging.
  14836.     myMenu add: ' layout ' action: #layout.
  14837.     myMenu add: ' center constraints ' action: #centerConstraints.    
  14838.     myMenu addLine.
  14839.  
  14840.     myMenu add: ' toggle constraint labels ' action: #toggleConstraintLabels.    
  14841.     myMenu add: ' toggle variable labels ' action: #toggleVariableLabels.    
  14842.     (model selected size == 1) ifTrue:
  14843.         [myMenu add: ' change label ' action: #changeLabel].    
  14844.  
  14845.     myMenu addLine.
  14846.     myMenu add: ' select current solution ' action: #currentSolution.
  14847.  
  14848.     myMenu addLine.
  14849.     myMenu add: ' update all current solutions ' action: #updateCurrentSolutions.
  14850.     myMenu add: ' update from thing ' action: #update.!
  14851.  
  14852. centerConstraints
  14853.     "Place constraints at the center of their operands."
  14854.  
  14855.     model centerConstraints.
  14856.     self redisplay.!
  14857.  
  14858. changeLabel
  14859.     "Change the label for a constraint or variable."
  14860.  
  14861.     | arg name |
  14862.     arg _ self argument.
  14863.     name _ FillInTheBlank
  14864.                 request: 'New label?'
  14865.                 initialAnswer: arg name.
  14866.     (name isEmpty not) ifTrue: [arg name: name].
  14867.     self redisplay.!
  14868.  
  14869. currentSolution
  14870.     "Select the current solution."
  14871.  
  14872.     model currentSolution.
  14873.     view displayScene.!
  14874.  
  14875. layout
  14876.     "Make a nice layout."
  14877.  
  14878.     model animateOn: view.
  14879.     self redisplay.!
  14880.  
  14881. toggleConstraintLabels
  14882.     "Toggle the visibility of my constraint labels."
  14883.  
  14884.     model toggleConstraintLabels.
  14885.     self redisplay.!
  14886.  
  14887. toggleVariableLabels
  14888.     "Toggle the visibility of my variable labels."
  14889.  
  14890.     model toggleVariableLabels.
  14891.     self redisplay.!
  14892.  
  14893. update
  14894.     "Update my model from the underlying Thing."
  14895.  
  14896.     model rebuildFromThing.
  14897.     self redisplay.!
  14898.  
  14899. updateCurrentSolutions
  14900.     "Update the current solutions of all partitions from the underlying Thing."
  14901.  
  14902.     model updateCurrentSolutions.
  14903.     self redisplay.! !
  14904.  
  14905. !ThingDebugController methodsFor: 'private'!
  14906.  
  14907. redisplay
  14908.     "Used when changing partitions. Fix the enclosing rectangle (since we now have a new set of graphical objects), then redisplay."
  14909.  
  14910.     view computeEnclosingRectangle.
  14911.     view displayView.! !
  14912.  
  14913. BasicThingController subclass: #StandAloneThingController
  14914.     instanceVariableNames: ''
  14915.     classVariableNames: ''
  14916.     poolDictionaries: ''
  14917.     category: 'ThingLabII-UI-Thing Views'!
  14918.  
  14919.  
  14920. !StandAloneThingController methodsFor: 'initialize-release'!
  14921.  
  14922. controlActivity
  14923.     "Circumvent click/double click gesture stuff."
  14924.  
  14925.     (sensor redButtonPressed) ifTrue: [^self dragAt: sensor cursorPoint].
  14926.     super controlActivity.!
  14927.  
  14928. model: aThingAdaptor
  14929.     "This message gets called when the view is first opened. I take this opportunity to put myself in 'run' mode."
  14930.  
  14931.     super model: aThingAdaptor.
  14932.     self run.! !
  14933.  
  14934. !StandAloneThingController methodsFor: 'reframing'!
  14935.  
  14936. reframe: extent
  14937.     "Find a FrameThing in my model and ensure that its topLeft corner is 0@0 and its bottomRight corner is the current extent. If there is no FrameThing or if it doesn't need to be updated, do nothing."
  14938.  
  14939.     | frame |
  14940.     frame _ nil.
  14941.     model thing allThingsDo:
  14942.         [: thing |
  14943.          (thing isMemberOf: FrameThing) ifTrue:
  14944.             [frame _ thing]].
  14945.  
  14946.     ((frame notNil) and:
  14947.        [(frame topLeft asPoint ~= (0@0)) |
  14948.         (frame bottomRight asPoint ~= extent)]) ifTrue:
  14949.         [frame
  14950.             setAll: #(topLeft.x topLeft.y bottomRight.x bottomRight.y)
  14951.             to: (Array
  14952.                 with: 0
  14953.                 with: 0
  14954.                 with: extent x
  14955.                 with: extent y)
  14956.             strength: #required.
  14957.          self makePlan].! !
  14958.  
  14959. !StandAloneThingController methodsFor: 'direct manipulation'!
  14960.  
  14961. addMenuItems: debugging
  14962.     "Answer my yellow-button menu given the current selection and possibly some other view or controller state. The goal is to present in the menu only those possibilities which are legal commands at this juncture. If debugging is true, present a additional options which might be useful to implementors and other gurus."
  14963.  
  14964.     | argCount |
  14965.     argCount _ model selected size.
  14966.  
  14967.     myMenu add: ' select all ' action: #selectAll.
  14968.     (model selected size > 0) ifTrue:
  14969.         [myMenu add: ' clear selection ' action: #clearSelection].
  14970.     myMenu addLine.
  14971.  
  14972.     (running)
  14973.         ifTrue:
  14974.             [myMenu add: ' pause ' action: #stop]
  14975.         ifFalse:
  14976.             [myMenu add: ' step ' action: #step.
  14977.              myMenu add: ' run ' action: #run].
  14978.     myMenu addLine.
  14979.  
  14980.     (argCount <= 1) ifTrue:
  14981.         [myMenu add: ' explain ' action: #explain].
  14982.     ((argCount <= 1) & debugging) ifTrue:
  14983.          [myMenu add: ' inspect ' action: #inspectThing].
  14984.     (debugging) ifTrue:
  14985.         [myMenu add: ' debugger ' action: #openDebugger].
  14986.     myMenu addLine.!
  14987.  
  14988. scrollAt: aPoint
  14989.     "This is a noop for StandAlongThingControllers."!
  14990.  
  14991. selectAreaAt: aPoint toggleFlag: toggleFlag
  14992.     "This is a noop for StandAlongThingControllers."! !
  14993.  
  14994. "*************** Class and System Initialization ***************"!
  14995.  
  14996.     "Put class initializations here (NOTE: verify these and check ordering):"!
  14997.     ArrowHead initialize!
  14998.     BusyCursor initialize!
  14999.     EquationTranslator initialize!
  15000.     Strength initialize!
  15001.     ThingLabII initialize!
  15002.     Thing initialize!
  15003.     PrimitiveThing initialize!
  15004.     ModuleCompilerView initialize!
  15005.     ThingLabIIControlPanel initialize!
  15006.     PartsBin initialize!
  15007.  
  15008.     "Initialize the ScreenController yellow button menu:"!
  15009.     ScreenController initialize!
  15010.     ScreenController allInstancesDo: [: c | c initializeYellowButtonMenu]!
  15011.  
  15012. "Th-th-that's all, Folks..."!
  15013.